]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/cygmon/v2_0/misc/monitor.c
Initial revision
[karo-tx-redboot.git] / packages / cygmon / v2_0 / misc / monitor.c
1 //==========================================================================
2 //
3 //      monitor.c
4 //
5 //      Monitor shell and main routines for CygMON the Wonder Monitor
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):    
44 // Contributors: gthomas, dmoseley
45 // Date:         1999-10-20
46 // Purpose:      Monitor shell and main routines for CygMON the Wonder Monitor
47 // Description:  
48 //               
49 //
50 //####DESCRIPTIONEND####
51 //
52 //=========================================================================
53
54 /* Platform-independent code for cygmon */
55
56 #include <stdlib.h>
57 #include <unistd.h>
58 #ifdef HAVE_BSP
59 #include <bsp/bsp.h>
60 #include <bsp/cpu.h>
61 #include <bsp/hex-utils.h>
62 #endif
63 #include <monitor.h>
64 #ifdef HAVE_BSP
65 #include "cpu_info.h"
66 #endif
67 #include <ledit.h>
68 #include <signal.h>
69 #include <string.h>
70 #include <ctype.h>
71
72 #if USE_CYGMON_PROTOTYPES
73 /* Use common prototypes */
74 /* Some of the composed board.h files compose these
75    prototypes redundently, but if they dont,
76    these are the common definitions */
77 #include "fmt_util.h"   /* Interface to string formatting utilities */
78 #include "tservice.h"   /* Interface to target specific services */
79 #include "generic-stub.h" /* from libstub */
80 #endif /* USE_CYGMON_PROTOTYPES */
81
82 static int  cygmon_handle_exception (int sigval);
83 static void monitor_take_control (void);
84
85 #if CYGMON_SYSTEM_SERVICES
86 extern int process_syscall (int syscall_num);
87 #elif defined (USE_ECOS_HAL_EXCEPTIONS)
88 static int cygmon_process_syscall (int sigval);
89 #endif
90
91 int stub_is_active = 0;
92 mem_addr_t last_pc;
93
94 #ifdef HAVE_BSP
95
96 #if !defined(USE_ECOS_HAL_EXCEPTIONS)
97 static int mon_dbg_handler(int exc_nr, void *regs);
98 static int mon_kill_handler(int exc_nr, void *regs);
99 #endif // USE_ECOS_HAL_EXCEPTIONS
100
101 #ifndef USE_ECOS_HAL_BREAKPOINTS
102 #define __is_breakpoint_function() (get_pc() == (target_register_t)bsp_breakinsn)
103 #endif
104
105 #ifdef __ECOS__
106 /*
107  * This global flag is used by generic-stub.c to communicate to us that we
108  * are processing the breakpoint function within Cygmon itself.
109  */
110 extern int processing_breakpoint_function;
111 #endif
112
113 /* Global pointer to current set of saved registers. */
114 void *mon_saved_regs;
115
116 /* Original BSP debug vector replaced by monitor. */
117 #if !defined(USE_ECOS_HAL_EXCEPTIONS)
118 static bsp_handler_t old_dbg_vec;
119 #endif // !defined(USE_ECOS_HAL_EXCEPTIONS)
120
121 #else
122 static int handle_signal (int signal_val);
123
124 __PFI user_signal_handler = NULL;
125 #endif
126
127 #if defined(__ECOS__)
128 #include <cyg/hal/hal_stub.h>
129 #endif
130
131 #if defined(__ECOS__) && !defined(PROCESS_EXCEPTION_VEC_PROTOTYPE_EXISTS)
132 #define PROCESS_EXCEPTION_VEC_PROTOTYPE_EXISTS
133 extern volatile __PFI (*__process_exception_vec)(int);
134 #endif
135
136
137 #ifdef MONITOR_CONTROL_INTERRUPTS
138 /* This is set if the user wants interrupts enabled in the monitor. */
139 static int monitor_interrupts_enabled;
140 #endif
141
142
143 #if NOMAIN
144 int monitor_main (int argc, char **argv) /* Suppress default main() junk */
145 #else
146 int main (int argc, char **argv)     
147 #endif
148 {
149 #ifdef HAVE_BSP
150   int  cur_port;
151   struct bsp_comm_info comm_info;
152 #else
153   /* Set up exception handling traps */
154   initialize_stub ();
155 #endif
156
157   initialize_mon ();
158
159 #ifdef HAVE_BSP
160   /* get info on debug channel */
161   cur_port = bsp_set_debug_comm(-1);
162   bsp_sysinfo(BSP_INFO_COMM, cur_port, &comm_info);
163
164   /*
165    * If we're using a network interface, don't install
166    * the cygmon vectors. Currently, we only support stub
167    * mode over a network connection.
168    */
169   if (comm_info.kind != BSP_COMM_ENET)
170     {
171       xprintf("\n");
172       version ();
173
174       /* replace original BSP debug and kill handler with ours */
175 #if !defined(USE_ECOS_HAL_EXCEPTIONS)
176       old_dbg_vec = bsp_install_dbg_handler(mon_dbg_handler);
177       (void)bsp_install_kill_handler(mon_kill_handler);
178 #else
179       /* replace original BSP debug and kill handler with ours using eCos stuff */
180       __process_exception_vec = (__PFI)cygmon_handle_exception;
181       __process_syscall_vec = cygmon_process_syscall;
182       __process_exit_vec = monitor_take_control;
183 #endif // __ECOS__
184     }
185   else
186     {
187       /* This forces the console to use the gdb channel. */
188       bsp_set_console_comm(cur_port);
189     }
190 #else
191   xprintf("\n");
192   version ();
193
194   __process_exception_vec = cygmon_handle_exception;
195   __process_exit_vec = monitor_take_control;
196 #if CYGMON_SYSTEM_SERVICES
197   __process_syscall_vec = process_syscall;
198 #endif  
199   __process_signal_vec = handle_signal;
200   __init_vec = install_breakpoints;
201   __cleanup_vec = clear_breakpoints;
202 #endif
203
204 #if 0
205 #ifdef __ECOS__
206   __process_exception_vec = cygmon_handle_exception;
207 #endif
208 #endif
209
210   while (1)
211     {
212       breakpoint ();
213       if (switch_to_stub_flag)
214         {
215           xprintf("Switching to stub\n");
216           switch_to_stub_flag = 0;
217         }
218     }
219
220   /* never reached */
221   exit (0);
222 }
223
224
225 /* Transfer control to gdb stub */
226  
227 int 
228 transfer_to_stub ()
229 {
230   /* Return back to the exception handler, but the exception handler
231      should invoke the stub's exception handler instead of ours. */
232 #if defined(HAVE_BSP) && !defined(USE_ECOS_HAL_EXCEPTIONS)
233   (void)bsp_install_dbg_handler(old_dbg_vec);
234 #else
235   __switch_to_stub ();
236 #endif
237
238   /* The stub is now active. */
239   stub_is_active = 1;
240   return -1;
241 }
242
243 void
244 clear_user_state (void)
245 {
246 #ifdef HAS_TIMER
247   if (__timer_enabled ())
248     __settimer (0, 0);
249 #endif
250
251   clear_breakpoints ();
252
253 #ifndef HAVE_BSP
254   user_signal_handler = NULL;
255 #endif
256
257   __clear_single_step ();
258 }
259
260 static void
261 monitor_take_control (void)
262 {
263   stub_is_active = 0;
264   switch_to_stub_flag = 0;
265
266   // Flush the unget state.  This is because the ecos stub and Cygmon track this
267   // stuff separately.
268   bsp_debug_ungetc('\0');
269
270 #ifdef INITIALIZE_MON_EACH_TIME
271   // Call the per-stop initialization routine if it is defined.
272   INITIALIZE_MON_EACH_TIME();
273 #endif
274
275 #if defined(HAVE_BSP) && !defined(USE_ECOS_HAL_EXCEPTIONS)
276   /* replace original BSP debug trap handler with ours */
277   (void)bsp_install_dbg_handler(mon_dbg_handler);
278 #else
279   clear_user_state ();
280   __process_exception_vec = cygmon_handle_exception;
281 #endif
282 }
283
284
285 #ifdef MONITOR_CONTROL_INTERRUPTS
286 void
287 monitor_enable_interrupts (void)
288 {
289   monitor_interrupts_enabled = 1;
290   enable_interrupts ();
291 }
292
293 void
294 monitor_disable_interrupts (void)
295 {
296   monitor_interrupts_enabled = 0;
297   disable_interrupts ();
298 }
299
300 int
301 monitor_interrupt_state (void)
302 {
303   return monitor_interrupts_enabled;
304 }
305 #endif
306
307 #if defined(USE_ECOS_HAL_EXCEPTIONS)
308 externC HAL_SavedRegisters *_hal_registers;
309 extern int machine_syscall(HAL_SavedRegisters *regs);
310 static int
311 cygmon_process_syscall (int sigval)
312 {
313     return machine_syscall(_hal_registers);
314 }
315 #endif
316
317 static int
318 cygmon_handle_exception (int sigval)
319 {
320   target_register_t pc;
321
322 #ifdef MONITOR_CONTROL_INTERRUPTS
323   if (monitor_interrupts_enabled)
324     {
325       if (! __in_interrupt)
326         enable_interrupts ();
327     }
328 #endif
329
330 #ifdef TARGET_EXCEPTION_CODE
331   TARGET_EXCEPTION_CODE
332 #endif
333
334 #ifndef HAVE_BSP
335   if (sigval != SIGKILL)
336     if (handle_signal (sigval) == 0)
337       return 0;
338 #endif
339
340   clear_user_state ();
341
342   /* We may want to tweak the PC to point at the faulting instruction,
343      for example. (breakpoints on x86). */
344 #ifdef TARGET_ADJUST_PC
345   TARGET_ADJUST_PC
346 #endif
347
348   pc = get_pc();
349   MAKE_STD_ADDR (pc, &last_pc);
350
351 #ifdef __ECOS__
352   if ((sigval == SIGTRAP) && (__is_breakpoint_function() || processing_breakpoint_function))
353 #else
354   if ((sigval == SIGTRAP) && __is_breakpoint_function())
355 #endif
356     {
357       /*
358        * This is the initial breakpoint inserted by the BSP
359        * Don't print anything for this as it is confusing
360        */
361     }
362   else
363     {
364       if (sigval == SIGTRAP)
365           xprintf ("Hit breakpoint");
366       else
367           xprintf ("Got signal %d", sigval);
368
369       xprintf (" at 0x%s\n", int2str (pc, 16, sizeof (target_register_t) * 2));
370
371 #ifdef DISASSEMBLER
372       if (!__is_breakpoint_function ())
373         {
374           do_dis (&last_pc);
375           flush_dis ();
376         }
377 #endif
378     }
379
380   monitor_take_control ();
381
382   return monitor_loop ();
383 }
384
385 #ifndef HAVE_BSP
386 /* Returns 0 if the program should restart at the point at which the
387    signal was received, -1 otherwise. */
388 static int
389 handle_signal (int signal)
390 {
391   if (signal == SIGKILL)
392     return -1;
393
394   if (user_signal_handler != NULL)
395     {
396       int result = user_signal_handler (signal);
397       switch (result)
398         {
399           /* Don't ignore potential hardware signals. */
400         case 3:
401           if (signal == SIGSEGV || signal == SIGBUS || signal == SIGFPE
402               || signal == SIGTRAP || signal == SIGILL)
403             return -1;
404
405         case 0:
406           return 0;
407
408         default:
409         case 1:
410         case 2:
411           return -1;
412         }
413     }
414     return -1;
415 }
416 #endif
417
418
419 void
420 version (void)
421 {
422 #ifdef HAVE_BSP
423   struct bsp_platform_info platform;
424   struct bsp_mem_info      mem;
425   int                      i;
426   unsigned long            u, totmem, topmem;
427 #endif
428   extern char *build_date;
429
430   xprintf ("Cygmon, the Cygnus ROM monitor.\n");
431   xprintf ("Copyright(c) 1997, 1998, 1999, 2000 Red Hat\n\n");
432   xprintf ("Version: %s\nThis image was built on %s\n\n",
433            VERSION, build_date);
434
435 #ifdef HAVE_BSP
436   bsp_sysinfo(BSP_INFO_PLATFORM, &platform);
437
438   totmem = topmem = 0;
439   i = 0;
440   while (bsp_sysinfo(BSP_INFO_MEMORY, i++, &mem) == 0)
441     {
442       if (mem.kind == BSP_MEM_RAM)
443         {
444           totmem += mem.nbytes;
445           u = (unsigned long)mem.virt_start + mem.nbytes;
446           if (u > topmem)
447             topmem = u;
448         }
449     }
450
451   xprintf("CPU: %s\n", platform.cpu);
452   xprintf("Board: %s\n", platform.board);
453   if (*(platform.extra))
454       xprintf("%s\n", platform.extra);
455   xprintf("Total RAM: %d bytes\n", totmem);
456   xprintf("Top of RAM: 0x%x\n", topmem);
457 #endif
458 }
459
460
461 #ifdef HAVE_BSP
462 #if !defined(USE_ECOS_HAL_EXCEPTIONS)
463 static int
464 mon_kill_handler(int exc_nr, void *regs)
465 {
466     monitor_take_control();
467     return 1;
468 }
469 #endif // !defined(USE_ECOS_HAL_EXCEPTIONS)
470
471 #if !defined(USE_ECOS_HAL_EXCEPTIONS)
472 static int
473 mon_dbg_handler(int exc_nr, void *regs)
474 {
475     int sig;
476     unsigned long cur_pc;
477
478     mon_saved_regs = regs;
479     sig = bsp_get_signal(exc_nr, regs);
480
481     cygmon_handle_exception(sig);
482
483     cur_pc = bsp_get_pc(regs);
484     if (cur_pc == (unsigned long)bsp_breakinsn)
485         bsp_skip_instruction(regs);
486
487     if (!stub_is_active)
488         install_breakpoints();
489
490     return 1;
491 }
492 #endif // !defined(USE_ECOS_HAL_EXCEPTIONS)
493
494 #endif