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!
13 class Jdb_entry_frame;
22 Msr_test_fail_warn = 1,
23 Msr_test_fail_ignore = 2,
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;
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;
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);
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;
53 SS_NONE=0, SS_BRANCH, SS_RETURN
56 static Per_cpu<Step_state> ss_state;
57 static Per_cpu<int> ss_level;
59 static const Unsigned8 *debug_ctrl_str;
60 static int debug_ctrl_len;
62 static Per_cpu<int> jdb_irqs_disabled;
65 IMPLEMENTATION [{amd64,ia32}-!serial]:
68 void Jdb::init_serial_console()
71 IMPLEMENTATION [{amd64,ia32}-serial]:
74 #include "kernel_uart.h"
77 void Jdb::init_serial_console()
79 if (Config::serial_esc == Config::SERIAL_ESC_IRQ &&
80 !Kernel_uart::uart()->failed())
84 if ((irq = Kernel_uart::uart()->irq()) == -1)
86 Config::serial_esc = Config::SERIAL_ESC_NOIRQ;
87 puts("SERIAL ESC: Using serial hack in slow timer handler.");
91 Kernel_uart::enable_rcv_irq();
92 printf("SERIAL ESC: allocated IRQ %d for serial uart\n", irq);
97 IMPLEMENTATION[ia32,amd64]:
105 #include "simpleio.h"
108 #include "boot_info.h"
109 #include "checksum.h"
113 #include "initcalls.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"
124 #include "mem_layout.h"
126 #include "push_console.h"
127 #include "processor.h"
129 #include "static_init.h"
130 #include "terminate.h"
132 #include "thread_state.h"
134 #include "trap_state.h"
137 #include "watchdog.h"
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
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
153 const Unsigned8*Jdb::debug_ctrl_str; // string+length for remote control of
154 int Jdb::debug_ctrl_len; // Jdb via enter_kdebugger("*#");
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;
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);
165 // available from the jdb_dump module
166 int jdb_dump_addr_task (Address addr, Space *task, int level)
167 __attribute__((weak));
170 STATIC_INITIALIZE_P(Jdb,JDB_INIT_PRIO);
173 IMPLEMENT FIASCO_INIT FIASCO_NOINLINE
176 if (strstr (Cmdline::cmdline(), " -nojdb"))
179 if (strstr (Cmdline::cmdline(), " -jdb_never_stop"))
182 init_serial_console();
184 Trap_state::base_handler = (Trap_state::Handler)enter_jdb;
186 // if esc_hack, serial_esc or watchdog enabled, set slow timer handler
187 Idt::set_vectors_run();
189 // disable lbr feature per default since it eats cycles on AMD Athlon boxes
190 Cpu::boot_cpu()->lbr_enable(false);
192 Kconsole::console()->register_console(push_cons());
194 Thread::set_int3_handler(handle_int3_threadctx);
197 Thread::may_enter_jdb = true;
200 PUBLIC static inline bool
206 PROTECTED static inline
208 Jdb::monitor_address(unsigned current_cpu, void *addr)
210 if (Cpu::cpus.cpu(current_cpu).has_monitor_mwait())
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) );
221 template <typename T> T
222 Jdb::peek(T const *addr)
228 template <typename T> T
229 Jdb::peek(T const *addr, Address_type)
231 // on IA32 we can touch directly into the user-space
244 static Per_cpu<Proc::Status> DEFINE_PER_CPU jdb_saved_flags;
246 // disable interrupts before entering the kernel debugger
249 Jdb::save_disable_irqs(unsigned cpu)
251 if (!jdb_irqs_disabled.cpu(cpu)++)
253 // save interrupt flags
254 jdb_saved_flags.cpu(cpu) = Proc::cli_save();
259 pic_status = Pic::disable_all_save();
261 if (Io_apic::active() && Apic::is_present())
263 apic_tpr.cpu(cpu) = Apic::tpr();
264 Apic::tpr(APIC_IRQ_BASE - 0x10);
267 if (cpu == 0 && Config::getchar_does_hlt && Config::getchar_does_hlt_works_ok)
269 // set timer interrupt does nothing than wakeup from hlt
270 Idt::set_vectors_stop();
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.
283 // restore interrupts after leaving the kernel debugger
286 Jdb::restore_irqs(unsigned cpu)
288 if (!--jdb_irqs_disabled.cpu(cpu))
292 if (Io_apic::active() && Apic::is_present())
293 Apic::tpr(apic_tpr.cpu(cpu));
297 Pic::restore_all(Jdb::pic_status);
301 // reset timer interrupt vector
302 if (cpu == 0 && Config::getchar_does_hlt && Config::getchar_does_hlt_works_ok)
303 Idt::set_vectors_run();
305 // reset interrupt flags
306 Proc::sti_restore(jdb_saved_flags.cpu(cpu));
313 Jdb::get_register(char *reg)
323 putchar(reg_name.c[0] = Jdb_screen::Reg_prefix);
330 putchar(reg_name.c[i] = c & 0xdf);
333 reg_name.c[3] = '\0';
336 if (reg_name.v == *((unsigned*)(Jdb_screen::Reg_names[i])))
349 On_dbg_stack(Mword sp) : sp(sp) {}
350 bool operator () (unsigned cpu) const
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;
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!
363 Jdb::get_thread(unsigned cpu)
365 Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
366 Address sp = (Address) entry_frame;
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
372 if (foreach_cpu(On_dbg_stack(sp), false))
375 if (sp >= boot_stack - 8192 && sp <= boot_stack + 8192)
378 return static_cast<Thread*>(context_of((const void*)sp));
383 Jdb::translate_task(Address addr, Space *task)
385 return (Kmem::is_kmem_page_fault(addr, 0)) ? 0 : task;
390 Jdb::peek_phys(Address phys, void *value, int width)
392 assert(!(phys & (width-1)));
394 Address virt = Kmem::map_phys_page_tmp(phys, 0);
396 memcpy(value, (void*)virt, width);
401 Jdb::poke_phys(Address phys, void const *value, int width)
403 assert(!(phys & (width-1)));
405 Address virt = Kmem::map_phys_page_tmp(phys, 0);
407 memcpy((void*)virt, value, width);
413 Jdb::peek_task(Address addr, Space *task, void *value, int width)
417 if (!task && Kmem::is_kmem_page_fault(addr, 0))
419 // address of kernel directory
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));
426 memcpy(value, (void*)addr, width);
430 // specific address space, use temporary mapping
435 // user address, use temporary mapping
436 phys = Address(task->mem_space()->virt_to_phys (addr));
439 phys = task->mem_space()->virt_to_phys_s0 ((void*)addr);
445 peek_phys(phys, value, width);
451 Jdb::poke_task(Address addr, Space *task, void const *value, int width)
455 if (task && Kmem::is_kmem_page_fault(addr, 0))
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));
463 memcpy((void*)addr, value, width);
472 // user address, use temporary mapping
473 phys = Address(task->mem_space()->virt_to_phys (addr));
476 phys = task->mem_space()->virt_to_phys_s0 ((void*)addr);
482 poke_phys(phys, value, width);
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.
491 Jdb::is_adapter_memory(Address virt, Space *task)
498 else if ( !Kmem::is_io_bitmap_page_fault(virt)
499 && Kmem::is_kmem_page_fault(virt, 0))
501 phys = Kmem::virt_to_phys((const void*)virt);
504 phys = task->mem_space()->virt_to_phys_s0((void*)virt);
509 Mem_desc *m = Kip::k()->mem_descs();
510 Mem_desc *e = m + Kip::k()->num_mem_descs();
512 if (m->type() == Mem_desc::Conventional && !m->is_virtual()
513 && m->start() <= phys && m->end() >= phys)
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;
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.
531 Jdb::Guessed_thread_state
532 Jdb::guess_thread_state(Thread *t)
534 Guessed_thread_state state = s_unknown;
535 Mword *ktop = (Mword*)((Mword)context_of(t->get_kernel_sp()) +
536 Config::thread_block_size);
538 for (int i=-1; i>-26; i--)
542 if (ktop[i] == (Mword)&in_page_fault)
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
556 else if (ktop[i] == (Mword)&in_syscall)
558 else if (ktop[i] == (Mword)&Thread::user_invoke)
559 state = s_user_invoke;
560 else if (ktop[i] == (Mword)&in_handle_fputrap)
562 else if (ktop[i] == (Mword)&in_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)
569 if (state != s_unknown)
574 if (state == s_unknown && (t->state() & Thread_ipc_mask))
582 Jdb::set_single_step(unsigned cpu, int on)
585 entry_frame.cpu(cpu)->flags(entry_frame.cpu(cpu)->flags() | EFLAGS_TF);
587 entry_frame.cpu(cpu)->flags(entry_frame.cpu(cpu)->flags() & ~EFLAGS_TF);
589 permanent_single_step.cpu(cpu) = on;
594 Jdb::handle_special_cmds(int c)
596 foreach_cpu(&analyze_code);
600 case 'j': // do restricted "go"
601 switch (putchar(c=getchar()))
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))
608 // increase call level because currently we
609 // stay on a call instruction
610 ss_level.cpu(current_cpu)++;
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);
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;
628 // ignore character and get next input
637 IMPLEMENTATION[ia32]:
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
643 Jdb::analyze_code(unsigned cpu)
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())
653 if ( !peek((Unsigned8*)entry_frame->ip(), task, op1)
654 || !peek((Unsigned8*)(entry_frame->ip()+1), task, op2))
657 if (op1 != 0x0f && op1 != 0xff)
661 ( ((op1 & 0xf6) == 0xc2) // ret/lret /xxxx
662 || (op1 == 0xcf)); // iret
665 ( (op1 == 0xe8) // call near
667 && ((op2 & 0x30) == 0x10)) // call/lcall *(...)
668 || (op1 == 0x9a)); // lcall xxxx:xxxx
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
676 && ((op2 & 0xf0) == 0x80)) // jxx rel 16/32 bit
678 && ((op2 & 0x30) == 0x20)) // jmp/ljmp *(...)
679 || (op1 == 0xea)); // ljmp xxxx:xxxx
682 ( (op1 == 0xcc) // int3
683 || (op1 == 0xcd) // int xx
684 || (op1 == 0xce)); // into
687 IMPLEMENTATION[amd64]:
690 Jdb::analyze_code(unsigned)
693 IMPLEMENTATION[ia32,amd64]:
695 // entered debugger because of single step trap
696 static inline NOEXPORT int
697 Jdb::handle_single_step(unsigned cpu)
699 int really_break = 1;
703 Cpu const &ccpu = Cpu::cpus.cpu(cpu);
705 // special single_step ('j' command): go until branch/return
706 if (ss_state.cpu(cpu) != SS_NONE)
708 if (ccpu.lbr_type() != Cpu::Lbr_unsupported)
710 // don't worry, the CPU always knows what she is doing :-)
714 // we have to emulate lbr looking at the code ...
715 switch (ss_state.cpu(cpu))
718 // go until function return
720 if (code_call.cpu(cpu))
722 // increase call level
725 else if (code_ret.cpu(cpu))
727 // decrease call level
728 really_break = (ss_level.cpu(cpu)-- == 0);
733 // go until next branch
734 really_break = (code_ret.cpu(cpu) || code_call.cpu(cpu) || code_bra.cpu(cpu) || code_int.cpu(cpu));
742 ss_state.cpu(cpu) = SS_NONE;
743 snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "Branch/Call");
746 else // (ss_state == SS_NONE)
747 // regular single_step
748 snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "Singlestep");
753 // entered debugger due to debug exception
754 static inline NOEXPORT int
755 Jdb::handle_trap1(unsigned cpu)
757 // FIXME: currently only on bot cpu
761 if (bp_test_sstep && bp_test_sstep())
762 return handle_single_step(cpu);
765 && bp_test_break(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0))))
769 && bp_test_other(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0))))
775 // entered debugger due to software breakpoint
776 static inline NOEXPORT int
777 Jdb::handle_trap3(unsigned cpu)
779 Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
780 Space *task = get_task(cpu);
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)
790 char const *msg = (char const*)(entry_frame->ip()+2);
792 if (!peek(msg, task, buffer[0]))
795 if (len > 1 && !peek(msg+1, task, buffer[1]))
798 // we are entering here because enter_kdebugger("*#..."); failed
799 if (len > 1 && buffer[0] == '*' && buffer[1] == '#')
806 if (len && peek(msg, task, buffer[2]))
809 if (buffer[2] == '#')
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++)
818 // a ``enter_kdebug("*#")'' sequence
819 for (i=0; i<sizeof(ctrl)-1 && i<len && peek(msg, task, tmp); i++, msg++)
823 snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)),
824 "invalid ctrl sequence \"%s\"", ctrl);
827 // enter_kdebugger("...");
831 len = len < 47 ? len : 47;
832 len = len < sizeof(error_buffer.cpu(0))-1
834 : sizeof(error_buffer.cpu(0))-1;
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';
844 // entered debugger due to other exception
845 static inline NOEXPORT int
846 Jdb::handle_trapX(unsigned cpu)
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);
859 /** Int3 debugger interface. This function is called immediately
860 * after entering the kernel debugger.
861 * @return 1 if command was successfully interpreted
865 Jdb::handle_user_request(unsigned cpu)
867 Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
869 if (entry_frame->_trapno == 3)
871 Space *task = get_task(cpu);
873 if (!peek((Unsigned8*)entry_frame->ip(), task, todo))
876 // jmp == enter_kdebug()
880 if (!peek((Unsigned8*)(entry_frame->ip()+1), task, len))
883 char const *str = (char const *)(entry_frame->ip()+2);
889 if (!peek(str, task, tmp) || tmp !='*')
892 if (!peek(str+1, task, tmp) || tmp != '#')
897 if (peek(str+2, task, tmp) && tmp == '#')
898 ret = execute_command_ni(task, (char const *)entry_frame->value());
900 ret = execute_command_ni(task, str+2, len-2);
906 else if (todo == 0x3c)
908 if (!peek((Unsigned8*)(entry_frame->ip()+1), task, todo))
914 if (entry_frame->value() == 3)
917 execute_command("Tgzip");
930 Jdb::enter_trap_handler(unsigned cpu)
931 { Cpu::cpus.cpu(cpu).debugctl_disable(); }
935 Jdb::leave_trap_handler(unsigned cpu)
936 { Cpu::cpus.cpu(cpu).debugctl_enable(); }
940 Jdb::handle_conditional_breakpoint(unsigned cpu)
941 { return entry_frame.cpu(cpu)->_trapno == 1 && bp_test_log_only && bp_test_log_only(); }
945 Jdb::handle_nested_trap(Jdb_entry_frame *e)
947 // re-enable interrupts if we need them because they are disabled
948 if (Config::getchar_does_hlt && Config::getchar_does_hlt_works_ok)
954 cursor(Jdb_screen::height(), 1);
955 printf("\nNMI occured\n");
958 cursor(Jdb_screen::height(), 1);
959 printf("\nSoftware breakpoint inside jdb at "L4_PTR_FMT"\n",
965 case Msr_test_fail_warn:
966 printf(" MSR does not exist or invalid value\n");
967 msr_test = Msr_test_default;
970 case Msr_test_fail_ignore:
971 msr_test = Msr_test_default;
975 cursor(Jdb_screen::height(), 1);
976 printf("\nGeneral Protection (eip="L4_PTR_FMT","
977 " err="L4_PTR_FMT") -- jdb bug?\n",
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") "
987 e->_trapno, e->_err, e->_cr2, e->ip());
994 Jdb::handle_debug_traps(unsigned cpu)
996 bool really_break = true;
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);
1003 really_break = handle_trapX(cpu);
1007 for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
1009 if (!Cpu::online(i) || !running.cpu(i))
1012 if (!permanent_single_step.cpu(i))
1013 entry_frame.cpu(i)->flags(entry_frame.cpu(i)->flags() & ~EFLAGS_TF);
1017 return really_break;
1022 Jdb::test_checksums()
1023 { return Boot_info::get_checksum_ro() == Checksum::get_checksum_ro(); }
1025 PUBLIC static inline
1027 Jdb::enter_getchar()
1030 PUBLIC static inline
1032 Jdb::leave_getchar()
1036 //----------------------------------------------------------------------------
1037 IMPLEMENTATION [(ia32 || amd64) && mp]:
1041 Jdb::send_nmi(unsigned cpu)
1043 Apic::mp_send_ipi(Cpu::cpus.cpu(cpu).phys_id(), 0, Apic::APIC_IPI_NMI);