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