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