]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/ia32/jdb-ia32-amd64.cpp
update
[l4.git] / kernel / fiasco / src / jdb / ia32 / jdb-ia32-amd64.cpp
1 // Inside Jdb the method Jdb::get_thread() should be used instead of
2 // Thread::current_thread(). The latter function cannot not handle the
3 // case when we came from the kernel stack context!
4
5 INTERFACE:
6
7 #include "l4_types.h"
8 #include "pic.h"
9
10 class Trap_state;
11 class Thread;
12 class Console_buffer;
13 class Jdb_entry_frame;
14 class Push_console;
15
16 EXTENSION class Jdb
17 {
18 public:
19   enum
20   {
21     Msr_test_default     = 0,
22     Msr_test_fail_warn   = 1,
23     Msr_test_fail_ignore = 2,
24   };
25
26   static void init();
27
28   static Per_cpu<unsigned> apic_tpr;
29   static Pic::Status pic_status;
30   static volatile char msr_test;
31   static volatile char msr_fail;
32
33   typedef enum
34     {
35       s_unknown, s_ipc, s_syscall, s_pagefault, s_fputrap,
36       s_interrupt, s_timer_interrupt, s_slowtrap, s_user_invoke,
37     } Guessed_thread_state;
38
39
40   static int (*bp_test_log_only)();
41   static int (*bp_test_sstep)();
42   static int (*bp_test_break)(char *errbuf, size_t bufsize);
43   static int (*bp_test_other)(char *errbuf, size_t bufsize);
44
45 private:
46
47   static char _connected;
48   static Per_cpu<char> permanent_single_step;
49   static Per_cpu<char> code_ret, code_call, code_bra, code_int;
50
51   typedef enum
52     {
53       SS_NONE=0, SS_BRANCH, SS_RETURN
54     } Step_state;
55
56   static Per_cpu<Step_state> ss_state;
57   static Per_cpu<int> ss_level;
58
59   static const Unsigned8 *debug_ctrl_str;
60   static int              debug_ctrl_len;
61
62   static Per_cpu<int> jdb_irqs_disabled;
63 };
64
65 IMPLEMENTATION [{amd64,ia32}-!serial]:
66
67 static inline
68 void Jdb::init_serial_console()
69 {}
70
71 IMPLEMENTATION [{amd64,ia32}-serial]:
72
73 #include <cstdio>
74 #include "kernel_uart.h"
75
76 static
77 void Jdb::init_serial_console()
78 {
79   if (Config::serial_esc == Config::SERIAL_ESC_IRQ &&
80       !Kernel_uart::uart()->failed())
81     {
82       int irq;
83
84       if ((irq = Kernel_uart::uart()->irq()) == -1)
85         {
86           Config::serial_esc = Config::SERIAL_ESC_NOIRQ;
87           puts("SERIAL ESC: Using serial hack in slow timer handler.");
88         }
89       else
90         {
91           Kernel_uart::enable_rcv_irq();
92           printf("SERIAL ESC: allocated IRQ %d for serial uart\n", irq);
93         }
94     }
95 }
96
97 IMPLEMENTATION[ia32,amd64]:
98
99 #include <cstring>
100 #include <csetjmp>
101 #include <cstdarg>
102 #include <climits>
103 #include <cstdlib>
104 #include <cstdio>
105 #include "simpleio.h"
106
107 #include "apic.h"
108 #include "boot_info.h"
109 #include "checksum.h"
110 #include "config.h"
111 #include "cpu.h"
112 #include "initcalls.h"
113 #include "idt.h"
114 #include "io_apic.h"
115 #include "jdb_core.h"
116 #include "jdb_screen.h"
117 #include "kernel_console.h"
118 #include "keycodes.h"
119 #include "kernel_uart.h"
120 #include "kernel_task.h"
121 #include "kmem.h"
122 #include "koptions.h"
123 #include "logdefs.h"
124 #include "mem_layout.h"
125 #include "pic.h"
126 #include "push_console.h"
127 #include "processor.h"
128 #include "regdefs.h"
129 #include "static_init.h"
130 #include "terminate.h"
131 #include "thread.h"
132 #include "thread_state.h"
133 #include "timer.h"
134 #include "trap_state.h"
135 #include "vkey.h"
136 #include "watchdog.h"
137
138 char Jdb::_connected;                   // Jdb::init() was done
139 // explicit single_step command
140 Per_cpu<char> DEFINE_PER_CPU Jdb::permanent_single_step;
141 volatile char Jdb::msr_test;            // = 1: trying to access an msr
142 volatile char Jdb::msr_fail;            // = 1: MSR access failed
143 Per_cpu<char> DEFINE_PER_CPU Jdb::code_ret; // current instruction is ret/iret
144 Per_cpu<char> DEFINE_PER_CPU Jdb::code_call;// current instruction is call
145 Per_cpu<char> DEFINE_PER_CPU Jdb::code_bra; // current instruction is jmp/jxx
146 Per_cpu<char> DEFINE_PER_CPU Jdb::code_int; // current instruction is int x
147
148 // special single step state
149 Per_cpu<Jdb::Step_state> DEFINE_PER_CPU Jdb::ss_state;
150 Per_cpu<int> DEFINE_PER_CPU Jdb::ss_level;  // current call level
151
152 const Unsigned8*Jdb::debug_ctrl_str;    // string+length for remote control of
153 int             Jdb::debug_ctrl_len;    // Jdb via enter_kdebugger("*#");
154
155 Pic::Status Jdb::pic_status;
156 Per_cpu<unsigned> DEFINE_PER_CPU Jdb::apic_tpr;
157 Per_cpu<int> DEFINE_PER_CPU Jdb::jdb_irqs_disabled;
158
159 int  (*Jdb::bp_test_log_only)();
160 int  (*Jdb::bp_test_sstep)();
161 int  (*Jdb::bp_test_break)(char *errbuf, size_t bufsize);
162 int  (*Jdb::bp_test_other)(char *errbuf, size_t bufsize);
163
164 // available from the jdb_dump module
165 int jdb_dump_addr_task (Address addr, Space *task, int level)
166   __attribute__((weak));
167
168
169 STATIC_INITIALIZE_P(Jdb,JDB_INIT_PRIO);
170
171
172 IMPLEMENT FIASCO_INIT FIASCO_NOINLINE
173 void Jdb::init()
174 {
175   if (Koptions::o()->opt(Koptions::F_nojdb))
176     return;
177
178   if (Koptions::o()->opt(Koptions::F_jdb_never_stop))
179     never_break = 1;
180
181   init_serial_console();
182
183   Trap_state::base_handler = (Trap_state::Handler)enter_jdb;
184
185   // if esc_hack, serial_esc or watchdog enabled, set slow timer handler
186   Idt::set_vectors_run();
187
188   // disable lbr feature per default since it eats cycles on AMD Athlon boxes
189   Cpu::boot_cpu()->lbr_enable(false);
190
191   Kconsole::console()->register_console(push_cons());
192
193   Thread::set_int3_handler(handle_int3_threadctx);
194
195   _connected = true;
196   Thread::may_enter_jdb = true;
197 }
198
199 PUBLIC static inline bool
200 Jdb::connected()
201 {
202   return _connected;
203 }
204
205 PROTECTED static inline
206 template< typename T >
207 void
208 Jdb::set_monitored_address(T *dest, T val)
209 {
210   *dest = val;
211 }
212
213 PROTECTED static inline
214 template< typename T >
215 T
216 Jdb::monitor_address(unsigned current_cpu, T *addr)
217 {
218   if (!*addr && Cpu::cpus.cpu(current_cpu).has_monitor_mwait())
219     {
220       asm volatile ("monitor \n" : : "a"(addr), "c"(0), "d"(0) );
221       Mword irq_sup = Cpu::cpus.cpu(current_cpu).has_monitor_mwait_irq() ? 1 : 0;
222       asm volatile ("mwait   \n" : : "a"(0x00), "c"(irq_sup) );
223     }
224
225   return *addr;
226 }
227
228
229 #if 0
230 PUBLIC static
231 template <typename T> T
232 Jdb::peek(T const *addr)
233 {
234   return *addr;
235 }
236
237 PUBLIC static
238 template <typename T> T
239 Jdb::peek(T const *addr, Address_type)
240 {
241   // on IA32 we can touch directly into the user-space
242   return *(T*)addr;
243 }
244 #endif
245
246 static inline
247 void
248 Jdb::backspace()
249 {
250   putstr("\b \b");
251 }
252
253
254 static Per_cpu<Proc::Status> DEFINE_PER_CPU jdb_saved_flags;
255
256 // disable interrupts before entering the kernel debugger
257 IMPLEMENT
258 void
259 Jdb::save_disable_irqs(unsigned cpu)
260 {
261   if (!jdb_irqs_disabled.cpu(cpu)++)
262     {
263       // save interrupt flags
264       jdb_saved_flags.cpu(cpu) = Proc::cli_save();
265
266       if (cpu == 0)
267         {
268           Watchdog::disable();
269           pic_status = Pic::disable_all_save();
270           if (Config::getchar_does_hlt && Config::getchar_does_hlt_works_ok)
271             Timer::disable();
272         }
273       if (Io_apic::active() && Apic::is_present())
274         {
275           apic_tpr.cpu(cpu) = Apic::tpr();
276           Apic::tpr(APIC_IRQ_BASE - 0x10);
277         }
278
279       if (cpu == 0 && Config::getchar_does_hlt && Config::getchar_does_hlt_works_ok)
280         {
281           // set timer interrupt does nothing than wakeup from hlt
282           Idt::set_vectors_stop();
283           Timer::enable();
284         }
285
286     }
287
288   if (cpu == 0 && Config::getchar_does_hlt && Config::getchar_does_hlt_works_ok)
289     // explicit enable interrupts because the timer interrupt is
290     // needed to wakeup from "hlt" state in getchar(). All other
291     // interrupts are disabled at the pic.
292     Proc::sti();
293 }
294
295 // restore interrupts after leaving the kernel debugger
296 IMPLEMENT
297 void
298 Jdb::restore_irqs(unsigned cpu)
299 {
300   if (!--jdb_irqs_disabled.cpu(cpu))
301     {
302       Proc::cli();
303
304       if (Io_apic::active() && Apic::is_present())
305         Apic::tpr(apic_tpr.cpu(cpu));
306
307       if (cpu == 0)
308         {
309           Pic::restore_all(Jdb::pic_status);
310           Watchdog::enable();
311         }
312
313       // reset timer interrupt vector
314       if (cpu == 0 && Config::getchar_does_hlt && Config::getchar_does_hlt_works_ok)
315         Idt::set_vectors_run();
316
317       // reset interrupt flags
318       Proc::sti_restore(jdb_saved_flags.cpu(cpu));
319     }
320 }
321
322
323 PUBLIC
324 static int
325 Jdb::get_register(char *reg)
326 {
327   union
328   {
329     char c[4];
330     Unsigned32 v;
331   } reg_name;
332
333   int i;
334
335   putchar(reg_name.c[0] = Jdb_screen::Reg_prefix);
336
337   for (i=1; i<3; i++)
338     {
339       int c = getchar();
340       if (c == KEY_ESC)
341         return false;
342       putchar(reg_name.c[i] = c & 0xdf);
343     }
344
345   reg_name.c[3] = '\0';
346
347   for (i=0; i<9; i++)
348     if (reg_name.v == *((unsigned*)(Jdb_screen::Reg_names[i])))
349       break;
350
351   if (i==9)
352     return false;
353   
354   *reg = i+1;
355   return true;
356 }
357
358 struct On_dbg_stack
359 {
360   Mword sp;
361   On_dbg_stack(Mword sp) : sp(sp) {}
362   bool operator () (unsigned cpu) const
363   {
364     Thread::Dbg_stack const &st = Thread::dbg_stack.cpu(cpu);
365     return sp <= Mword(st.stack_top) 
366        && sp >= Mword(st.stack_top) - Thread::Dbg_stack::Stack_size;
367   }
368 };
369
370 // Do thread lookup using Trap_state. In contrast to Thread::current_thread()
371 // this function can also handle cases where we entered from kernel stack
372 // context. We _never_ return 0!
373 IMPLEMENT
374 Thread*
375 Jdb::get_thread(unsigned cpu)
376 {
377   Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
378   Address sp = (Address) entry_frame;
379
380   // special case since we come from the double fault handler stack
381   if (entry_frame->_trapno == 8 && !(entry_frame->cs() & 3))
382     sp = entry_frame->sp(); // we can trust esp since it comes from main_tss
383
384   if (foreach_cpu(On_dbg_stack(sp), false))
385     return 0;
386
387   if (sp >= boot_stack - 8192 && sp <= boot_stack + 8192)
388     return 0;
389
390   return static_cast<Thread*>(context_of((const void*)sp));
391 }
392
393 PUBLIC static
394 Space *
395 Jdb::translate_task(Address addr, Space *task)
396 {
397   return (Kmem::is_kmem_page_fault(addr, 0)) ? 0 : task;
398 }
399
400 PUBLIC static
401 void
402 Jdb::peek_phys(Address phys, void *value, int width)
403 {
404   assert(!(phys & (width-1)));
405
406   Address virt = Kmem::map_phys_page_tmp(phys, 0);
407
408   memcpy(value, (void*)virt, width);
409 }
410
411 PUBLIC static
412 void
413 Jdb::poke_phys(Address phys, void const *value, int width)
414 {
415   assert(!(phys & (width-1)));
416
417   Address virt = Kmem::map_phys_page_tmp(phys, 0);
418
419   memcpy((void*)virt, value, width);
420 }
421
422
423 PUBLIC static
424 int
425 Jdb::peek_task(Address addr, Space *task, void *value, int width)
426 {
427   Address phys;
428
429   if (!task && Kmem::is_kmem_page_fault(addr, 0))
430     {
431       // address of kernel directory
432       Address pdbr;
433       asm volatile ("mov %%cr3, %0" : "=r" (pdbr));
434       Pdir *kdir = (Pdir*)Mem_layout::phys_to_pmem(pdbr);
435       Pdir::Iter i = kdir->walk(Virt_addr(addr));
436       if (i.e->valid())
437         {
438           memcpy(value, (void*)addr, width);
439           return 0;
440         }
441     }
442   // specific address space, use temporary mapping
443   if (!task)
444     phys = addr;
445   else
446     {
447       // user address, use temporary mapping
448       phys = Address(task->mem_space()->virt_to_phys (addr));
449
450       if (phys == ~0UL)
451         phys = task->mem_space()->virt_to_phys_s0 ((void*)addr);
452
453       if (phys == ~0UL)
454         return -1;
455     }
456
457   peek_phys(phys, value, width);
458   return 0;
459 }
460
461 PUBLIC static
462 int
463 Jdb::poke_task(Address addr, Space *task, void const *value, int width)
464 {
465   Address phys;
466
467   if (task && Kmem::is_kmem_page_fault(addr, 0))
468     {
469       Address pdbr;
470       asm volatile ("mov %%cr3, %0" : "=r" (pdbr));
471       Pdir *kdir = (Pdir*)Mem_layout::phys_to_pmem(pdbr);
472       Pdir::Iter i = kdir->walk(Virt_addr(addr));
473       if (i.e->valid())
474         {
475           memcpy((void*)addr, value, width);
476           return 0;
477         }
478     }
479
480   if (!task)
481     phys = addr;
482   else
483     {
484       // user address, use temporary mapping
485       phys = Address(task->mem_space()->virt_to_phys (addr));
486
487       if (phys == ~0UL)
488         phys = task->mem_space()->virt_to_phys_s0 ((void*)addr);
489
490       if (phys == ~0UL)
491         return -1;
492     }
493
494   poke_phys(phys, value, width);
495   return 0;
496 }
497
498 // The content of apdapter memory is not shown by default because reading
499 // memory-mapped I/O registers may confuse the hardware. We assume that all
500 // memory above the end of the RAM is adapter memory.
501 PUBLIC static
502 int
503 Jdb::is_adapter_memory(Address virt, Space *task)
504 {
505   Address phys;
506
507   if (!task)
508     // phys requested
509     phys = virt;
510   else if (   !Kmem::is_io_bitmap_page_fault(virt)
511            &&  Kmem::is_kmem_page_fault(virt, 0))
512     // kernel address
513     phys = Kmem::virt_to_phys((const void*)virt);
514   else
515     // user address
516     phys = task->mem_space()->virt_to_phys_s0((void*)virt);
517
518   if (phys == ~0UL)
519     return false;
520
521   Mem_desc *m = Kip::k()->mem_descs();
522   Mem_desc *e = m + Kip::k()->num_mem_descs();
523   for (; m != e; ++m)
524     if (m->type() == Mem_desc::Conventional && !m->is_virtual()
525         && m->start() <= phys && m->end() >= phys)
526       return false;
527
528   return true;
529 }
530
531 #define WEAK __attribute__((weak))
532 extern "C" char in_slowtrap, in_page_fault, in_handle_fputrap;
533 extern "C" char in_interrupt, in_timer_interrupt, in_timer_interrupt_slow;
534 extern "C" char i30_ret_switch WEAK, se_ret_switch WEAK, in_slow_ipc1 WEAK;
535 extern "C" char in_slow_ipc2 WEAK, in_slow_ipc4;
536 extern "C" char in_slow_ipc5, in_sc_ipc1 WEAK;
537 extern "C" char in_sc_ipc2 WEAK, in_syscall WEAK;
538 #undef WEAK
539
540 // Try to guess the thread state of t by walking down the kernel stack and
541 // locking at the first return address we find.
542 PUBLIC static
543 Jdb::Guessed_thread_state
544 Jdb::guess_thread_state(Thread *t)
545 {
546   Guessed_thread_state state = s_unknown;
547   Mword *ktop = (Mword*)((Mword)context_of(t->get_kernel_sp()) +
548                           Config::thread_block_size);
549
550   for (int i=-1; i>-26; i--)
551     {
552       if (ktop[i] != 0)
553         {
554           if (ktop[i] == (Mword)&in_page_fault)
555             state = s_pagefault;
556           if ((ktop[i] == (Mword)&i30_ret_switch) ||// shortcut.S, int 0x30
557               (ktop[i] == (Mword)&in_slow_ipc1) ||  // shortcut.S, int 0x30
558               (ktop[i] == (Mword)&se_ret_switch) || // shortcut.S, sysenter
559               (ktop[i] == (Mword)&in_slow_ipc2) ||  // shortcut.S, sysenter
560               (ktop[i] == (Mword)&in_slow_ipc4) ||  // entry.S, int 0x30 log
561               (ktop[i] == (Mword)&in_slow_ipc5) ||  // entry.S, sysenter log
562 #if defined (CONFIG_JDB_LOGGING) || !defined(CONFIG_ASSEMBLER_IPC_SHORTCUT)
563               (ktop[i] == (Mword)&in_sc_ipc1)   ||  // entry.S, int 0x30
564               (ktop[i] == (Mword)&in_sc_ipc2)   ||  // entry.S, sysenter
565 #endif
566              0)
567             state = s_ipc;
568           else if (ktop[i] == (Mword)&in_syscall)
569             state = s_syscall;
570           else if (ktop[i] == (Mword)&Thread::user_invoke)
571             state = s_user_invoke;
572           else if (ktop[i] == (Mword)&in_handle_fputrap)
573             state = s_fputrap;
574           else if (ktop[i] == (Mword)&in_interrupt)
575             state = s_interrupt;
576           else if ((ktop[i] == (Mword)&in_timer_interrupt) ||
577                    (ktop[i] == (Mword)&in_timer_interrupt_slow))
578             state = s_timer_interrupt;
579           else if (ktop[i] == (Mword)&in_slowtrap)
580             state = s_slowtrap;
581           if (state != s_unknown)
582             break;
583         }
584     }
585
586   if (state == s_unknown && (t->state(false) & Thread_ipc_mask))
587     state = s_ipc;
588
589   return state;
590 }
591
592 PUBLIC static
593 void
594 Jdb::set_single_step(unsigned cpu, int on)
595 {
596   if (on)
597     entry_frame.cpu(cpu)->flags(entry_frame.cpu(cpu)->flags() | EFLAGS_TF);
598   else
599     entry_frame.cpu(cpu)->flags(entry_frame.cpu(cpu)->flags() & ~EFLAGS_TF);
600
601   permanent_single_step.cpu(cpu) = on;
602 }
603
604
605 static bool
606 Jdb::handle_special_cmds(int c)
607 {
608   foreach_cpu(&analyze_code);
609
610   switch (c)
611     {
612     case 'j': // do restricted "go"
613       switch (putchar(c=getchar()))
614         {
615         case 'b': // go until next branch
616         case 'r': // go until current function returns
617           ss_level.cpu(current_cpu) = 0;
618           if (code_call.cpu(current_cpu))
619             {
620               // increase call level because currently we
621               // stay on a call instruction
622               ss_level.cpu(current_cpu)++;
623             }
624           ss_state.cpu(current_cpu) = (c == 'b') ? SS_BRANCH : SS_RETURN;
625           // if we have lbr feature, the processor treats the single
626           // step flag as step on branches instead of step on instruction
627           Cpu::boot_cpu()->btf_enable(true);
628           // fall through
629         case 's': // do one single step
630           entry_frame.cpu(current_cpu)->flags(entry_frame.cpu(current_cpu)->flags() | EFLAGS_TF);
631           hide_statline = false;
632           return 0;
633         default:
634           abort_command();
635           break;
636         }
637       break;
638     default:
639       backspace();
640       // ignore character and get next input
641       break;
642     }
643
644   return 1;
645
646 }
647
648
649 IMPLEMENTATION[ia32]:
650
651 // take a look at the code of the current thread eip
652 // set global indicators code_call, code_ret, code_bra, code_int
653 // This can fail if the current page is still not mapped
654 static void
655 Jdb::analyze_code(unsigned cpu)
656 {
657   Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
658   Space *task = get_task(cpu);
659   // do nothing if page not mapped into this address space
660   if (entry_frame->ip()+1 > Kmem::user_max())
661     return;
662
663   Unsigned8 op1, op2;
664
665   if (   !peek((Unsigned8*)entry_frame->ip(), task, op1)
666       || !peek((Unsigned8*)(entry_frame->ip()+1), task, op2))
667     return;
668
669   if (op1 != 0x0f && op1 != 0xff)
670     op2 = 0;
671
672   code_ret.cpu(cpu) =
673               (   ((op1 & 0xf6) == 0xc2)        // ret/lret /xxxx
674                || (op1 == 0xcf));               // iret
675
676   code_call.cpu(cpu) =
677               (   (op1 == 0xe8)                 // call near
678                || ((op1 == 0xff)
679                    && ((op2 & 0x30) == 0x10))   // call/lcall *(...)
680                || (op1 == 0x9a));               // lcall xxxx:xxxx
681
682   code_bra.cpu(cpu) =
683               (   ((op1 & 0xfc) == 0xe0)        // loop/jecxz
684                || ((op1 & 0xf0) == 0x70)        // jxx rel 8 bit
685                || (op1 == 0xeb)                 // jmp rel 8 bit
686                || (op1 == 0xe9)                 // jmp rel 16/32 bit
687                || ((op1 == 0x0f)
688                    && ((op2 & 0xf0) == 0x80))   // jxx rel 16/32 bit
689                || ((op1 == 0xff)
690                    && ((op2 & 0x30) == 0x20))   // jmp/ljmp *(...)
691                || (op1 == 0xea));               // ljmp xxxx:xxxx
692
693   code_int.cpu(cpu) =
694               (   (op1 == 0xcc)                 // int3
695                || (op1 == 0xcd)                 // int xx
696                || (op1 == 0xce));               // into
697 }
698
699 IMPLEMENTATION[amd64]:
700
701 static void
702 Jdb::analyze_code(unsigned)
703 {}
704
705 IMPLEMENTATION[ia32,amd64]:
706
707 // entered debugger because of single step trap
708 static inline NOEXPORT int
709 Jdb::handle_single_step(unsigned cpu)
710 {
711   int really_break = 1;
712
713   analyze_code(cpu);
714
715   Cpu const &ccpu = Cpu::cpus.cpu(cpu);
716
717   // special single_step ('j' command): go until branch/return
718   if (ss_state.cpu(cpu) != SS_NONE)
719     {
720       if (ccpu.lbr_type() != Cpu::Lbr_unsupported)
721         {
722           // don't worry, the CPU always knows what she is doing :-)
723         }
724       else
725         {
726           // we have to emulate lbr looking at the code ...
727           switch (ss_state.cpu(cpu))
728             {
729             case SS_RETURN:
730               // go until function return
731               really_break = 0;
732               if (code_call.cpu(cpu))
733                 {
734                   // increase call level
735                   ss_level.cpu(cpu)++;
736                 }
737               else if (code_ret.cpu(cpu))
738                 {
739                   // decrease call level
740                   really_break = (ss_level.cpu(cpu)-- == 0);
741                 }
742               break;
743             case SS_BRANCH:
744             default:
745               // go until next branch
746               really_break = (code_ret.cpu(cpu) || code_call.cpu(cpu) || code_bra.cpu(cpu) || code_int.cpu(cpu));
747               break;
748             }
749         }
750
751       if (really_break)
752         {
753           // condition met
754           ss_state.cpu(cpu) = SS_NONE;
755           snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "Branch/Call");
756         }
757     }
758   else // (ss_state == SS_NONE)
759     // regular single_step
760     snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "Singlestep");
761
762   return really_break;
763 }
764
765 // entered debugger due to debug exception
766 static inline NOEXPORT int
767 Jdb::handle_trap1(unsigned cpu)
768 {
769   // FIXME: currently only on bot cpu
770   if (cpu != 0)
771     return 0;
772
773   if (bp_test_sstep && bp_test_sstep())
774     return handle_single_step(cpu);
775
776   if (bp_test_break
777       && bp_test_break(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0))))
778     return 1;
779
780   if (bp_test_other
781       && bp_test_other(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0))))
782     return 1;
783
784   return 0;
785 }
786
787 // entered debugger due to software breakpoint
788 static inline NOEXPORT int
789 Jdb::handle_trap3(unsigned cpu)
790 {
791   Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
792   Space *task = get_task(cpu);
793   Unsigned8 op;
794   Unsigned8 len;
795
796   snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "INT 3");
797   if (   !peek((Unsigned8*)entry_frame->ip(), task, op)
798       || !peek((Unsigned8*)(entry_frame->ip()+1), task, len)
799       || op != 0xeb)
800     return 1;
801
802   char const *msg = (char const*)(entry_frame->ip()+2);
803   char buffer[3];
804   if (!peek(msg, task, buffer[0]))
805     return 1;
806
807   if (len > 1 && !peek(msg+1, task, buffer[1]))
808     return 1;
809
810   // we are entering here because enter_kdebugger("*#..."); failed
811   if (len > 1 && buffer[0] == '*' && buffer[1] == '#')
812     {
813       unsigned i;
814       char ctrl[29];
815
816       len-=2;
817       msg+=2;
818       if (len && peek(msg, task, buffer[2]))
819         {
820           char tmp;
821           if (buffer[2] == '#')
822             {
823               // the ``-jdb_cmd='' sequence
824               msg = (char const*)entry_frame->value();
825               for (i=0; i<sizeof(ctrl)-1 && peek(msg, task, tmp) && tmp; i++, msg++)
826                 ctrl[i] = tmp;
827             }
828           else
829             {
830               // a ``enter_kdebug("*#")'' sequence
831               for (i=0; i<sizeof(ctrl)-1 && i<len && peek(msg, task, tmp); i++, msg++)
832                 ctrl[i] = tmp;
833             }
834           ctrl[i] = '\0';
835           snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)),
836               "invalid ctrl sequence \"%s\"", ctrl);
837         }
838     }
839   // enter_kdebugger("...");
840   else if (len > 0)
841     {
842       unsigned i;
843       len = len < 47 ? len : 47;
844       len =   len < sizeof(error_buffer.cpu(0))-1
845             ? len
846             : sizeof(error_buffer.cpu(0))-1;
847
848       for(i=0; i<len && peek(msg+i, task, buffer[0]); i++)
849         error_buffer.cpu(cpu)[i] = buffer[0];
850       error_buffer.cpu(cpu)[i]='\0';
851     }
852
853   return 1;
854 }
855
856 // entered debugger due to other exception
857 static inline NOEXPORT int
858 Jdb::handle_trapX(unsigned cpu)
859 {
860   unsigned pos = snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s",
861                           Cpu::exception_string(entry_frame.cpu(cpu)->_trapno)) + 1;
862   if (   pos < sizeof(error_buffer.cpu(0))
863       && entry_frame.cpu(cpu)->_trapno >= 10
864       && entry_frame.cpu(cpu)->_trapno <= 14)
865     snprintf(error_buffer.cpu(cpu)+pos, sizeof(error_buffer.cpu(0))-pos,
866              "(ERR="L4_PTR_FMT")", entry_frame.cpu(cpu)->_err);
867
868   return 1;
869 }
870
871 /** Int3 debugger interface. This function is called immediately
872  * after entering the kernel debugger.
873  * @return 1 if command was successfully interpreted
874  */
875 IMPLEMENT
876 bool
877 Jdb::handle_user_request(unsigned cpu)
878 {
879   Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
880
881   if (entry_frame->_trapno == 3)
882     {
883       Space *task = get_task(cpu);
884       Unsigned8 todo;
885       if (!peek((Unsigned8*)entry_frame->ip(), task, todo))
886         return false;
887
888       // jmp == enter_kdebug()
889       if (todo == 0xeb)
890         {
891           Unsigned8 len;
892           if (!peek((Unsigned8*)(entry_frame->ip()+1), task, len))
893             return false;
894
895           char const *str = (char const *)(entry_frame->ip()+2);
896           char tmp;
897
898           if (len <= 2)
899             return false;
900
901           if (!peek(str, task, tmp) || tmp !='*')
902             return false;
903
904           if (!peek(str+1, task, tmp) || tmp != '#')
905             return false;
906
907           int ret;
908
909           if (peek(str+2, task, tmp) && tmp == '#')
910             ret = execute_command_ni(task, (char const *)entry_frame->value());
911           else
912             ret = execute_command_ni(task, str+2, len-2);
913
914           if (ret)
915             return 1;
916         }
917       // cmpb
918       else if (todo == 0x3c)
919         {
920           if (!peek((Unsigned8*)(entry_frame->ip()+1), task, todo))
921             return false;
922
923           switch (todo)
924             {
925             case 29:
926               if (entry_frame->value() == 3)
927                 {
928                   Watchdog::disable();
929                   execute_command("Tgzip");
930                   Watchdog::enable();
931                   return 1;
932                 }
933               break;
934             }
935         }
936     }
937   return 0;
938 }
939
940 IMPLEMENT
941 void
942 Jdb::enter_trap_handler(unsigned cpu)
943 { Cpu::cpus.cpu(cpu).debugctl_disable(); }
944
945 IMPLEMENT
946 void
947 Jdb::leave_trap_handler(unsigned cpu)
948 { Cpu::cpus.cpu(cpu).debugctl_enable(); }
949
950 IMPLEMENT
951 bool
952 Jdb::handle_conditional_breakpoint(unsigned cpu)
953 { return entry_frame.cpu(cpu)->_trapno == 1 && bp_test_log_only && bp_test_log_only(); }
954
955 IMPLEMENT
956 void
957 Jdb::handle_nested_trap(Jdb_entry_frame *e)
958 {
959   // re-enable interrupts if we need them because they are disabled
960   if (Config::getchar_does_hlt && Config::getchar_does_hlt_works_ok)
961     Proc::sti();
962
963   switch (e->_trapno)
964     {
965     case 2:
966       cursor(Jdb_screen::height(), 1);
967       printf("\nNMI occured\n");
968       break;
969     case 3:
970       cursor(Jdb_screen::height(), 1);
971       printf("\nSoftware breakpoint inside jdb at "L4_PTR_FMT"\n",
972              e->ip()-1);
973       break;
974     case 13:
975       switch (msr_test)
976         {
977         case Msr_test_fail_warn:
978           printf(" MSR does not exist or invalid value\n");
979           msr_test = Msr_test_default;
980           msr_fail = 1;
981           break;
982         case Msr_test_fail_ignore:
983           msr_test = Msr_test_default;
984           msr_fail = 1;
985           break;
986         default:
987           cursor(Jdb_screen::height(), 1);
988           printf("\nGeneral Protection (eip="L4_PTR_FMT","
989               " err="L4_PTR_FMT") -- jdb bug?\n",
990               e->ip(), e->_err);
991           break;
992         }
993       break;
994     default:
995       cursor(Jdb_screen::height(), 1);
996       printf("\nInvalid access (trap=%02lx err="L4_PTR_FMT
997           " pfa="L4_PTR_FMT" eip="L4_PTR_FMT") "
998           "-- jdb bug?\n",
999           e->_trapno, e->_err, e->_cr2, e->ip());
1000       break;
1001     }
1002 }
1003
1004 IMPLEMENT
1005 bool
1006 Jdb::handle_debug_traps(unsigned cpu)
1007 {
1008   bool really_break = true;
1009
1010   if (entry_frame.cpu(cpu)->_trapno == 1)
1011     really_break = handle_trap1(cpu);
1012   else if (entry_frame.cpu(cpu)->_trapno == 3)
1013     really_break = handle_trap3(cpu);
1014   else
1015     really_break = handle_trapX(cpu);
1016
1017   if (really_break)
1018     {
1019       for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
1020         {
1021           if (!Cpu::online(i) || !running.cpu(i))
1022             continue;
1023           // else S+ mode
1024           if (!permanent_single_step.cpu(i))
1025             entry_frame.cpu(i)->flags(entry_frame.cpu(i)->flags() & ~EFLAGS_TF);
1026         }
1027     }
1028
1029   return really_break;
1030 }
1031
1032 IMPLEMENT
1033 bool
1034 Jdb::test_checksums()
1035 { return Boot_info::get_checksum_ro() == Checksum::get_checksum_ro(); }
1036
1037 PUBLIC static inline
1038 void
1039 Jdb::enter_getchar()
1040 {}
1041
1042 PUBLIC static inline
1043 void
1044 Jdb::leave_getchar()
1045 {}
1046
1047
1048 //----------------------------------------------------------------------------
1049 IMPLEMENTATION [(ia32 || amd64) && mp]:
1050
1051 static
1052 void
1053 Jdb::send_nmi(unsigned cpu)
1054 {
1055   Apic::mp_send_ipi(Cpu::cpus.cpu(cpu).phys_id(), 0, Apic::APIC_IPI_NMI);
1056 }