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