17 s_unknown, s_ipc, s_syscall, s_pagefault, s_fputrap,
18 s_interrupt, s_timer_interrupt, s_slowtrap, s_user_invoke,
19 } Guessed_thread_state;
21 enum { MIN_SCREEN_HEIGHT = 20, MIN_SCREEN_WIDTH = 80 };
23 template < typename T > static T peek(T const *addr, Address_type user);
25 static int (*bp_test_log_only)();
26 static int (*bp_test_break)(String_buffer *buf);
29 static unsigned short rows, cols;
37 #include <sys/ioctl.h>
42 #include "initcalls.h"
44 #include "jdb_dbinfo.h"
45 #include "jdb_screen.h"
46 #include "kernel_console.h"
47 #include "kernel_task.h"
48 #include "kernel_thread.h"
51 #include "libc_support.h"
53 #include "mem_layout.h"
54 #include "push_console.h"
57 #include "static_init.h"
59 #include "thread_state.h"
60 #include "trap_state.h"
64 int (*Jdb::bp_test_log_only)();
65 int (*Jdb::bp_test_break)(String_buffer *buf);
67 unsigned short Jdb::rows, Jdb::cols;
69 static Proc::Status jdb_irq_state;
73 Jdb::enter_trap_handler(Cpu_number)
77 // Set terminal raw mode
80 // Flush all output streams
86 Jdb::leave_trap_handler(Cpu_number)
88 // Restore terminal mode
91 // Flush all output streams
98 Jdb::handle_user_request(Cpu_number)
103 Jdb::test_checksums()
107 // disable interrupts before entering the kernel debugger
110 Jdb::save_disable_irqs(Cpu_number cpu)
112 assert(cpu == Cpu_number::boot_cpu());
113 jdb_irq_state = Proc::cli_save();
116 // restore interrupts after leaving the kernel debugger
119 Jdb::restore_irqs(Cpu_number cpu)
121 assert(cpu == Cpu_number::boot_cpu());
122 Proc::sti_restore(jdb_irq_state);
125 STATIC_INITIALIZE_P(Jdb,JDB_INIT_PRIO);
127 PUBLIC static FIASCO_INIT
131 // Install JDB handler
132 Trap_state::base_handler = (Trap_state::Handler)enter_jdb;
134 // be sure that Push_console comes very first
135 Kconsole::console()->register_console(push_cons()),
137 register_libc_atexit(leave_getchar);
138 atexit(leave_getchar);
140 Thread::set_int3_handler(handle_int3_threadctx);
148 ioctl (fileno (stdin), TIOCGWINSZ, &win);
152 if (rows < MIN_SCREEN_HEIGHT || cols < MIN_SCREEN_WIDTH)
153 printf ("%sTerminal probably too small, should be at least %dx%d!\033[0m\n",
154 esc_emph, MIN_SCREEN_WIDTH, MIN_SCREEN_HEIGHT);
156 Jdb_screen::set_height(rows);
157 Jdb_screen::set_width(cols);
160 /** handle int3 debug extension */
161 PUBLIC static inline NOEXPORT
163 Jdb::int3_extension()
165 Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(Cpu_number::boot_cpu());
166 Address addr = entry_frame->ip();
167 Address_type user = (entry_frame->cs() & 3) ? ADDR_USER : ADDR_KERNEL;
168 Unsigned8 todo = peek ((Unsigned8 *) addr, user);
169 Space *space = NULL; //get_task_id(0);
170 error_buffer.cpu(Cpu_number::boot_cpu()).clear();
172 if (todo == 0x3c && peek ((Unsigned8 *) (addr+1), user) == 13)
175 entry_frame->_ax = Vkey::get();
180 else if (todo != 0xeb)
182 error_buffer.cpu(Cpu_number::boot_cpu()).printf("INT 3");
186 // todo == 0xeb => enter_kdebug()
188 Mword len = peek ((Unsigned8 *) ++addr, user);
191 peek (((Unsigned8 *) addr + 1), user) == '*' &&
192 peek (((Unsigned8 *) addr + 2), user) == '#')
194 char c = peek (((Unsigned8 *) addr + 3), user);
197 ? execute_command_ni(space, (char const *) entry_frame->_ax)
198 : execute_command_ni(space, (char const *)(addr + 3), len-2))
199 return 1; // => leave Jdb
202 for (i = 0; i < len; i++)
203 error_buffer.cpu(Cpu_number::boot_cpu()).append(peek ((Unsigned8 *) ++addr, user));
204 error_buffer.cpu(Cpu_number::boot_cpu()).terminate();
210 Jdb::handle_special_cmds(int)
215 Jdb::handle_debug_traps(Cpu_number cpu)
217 error_buffer.cpu(cpu).clear();
218 switch (entry_frame.cpu(cpu)->_trapno)
221 error_buffer.cpu(cpu).printf("Interception");
224 if (int3_extension())
227 if (get_thread(cpu)->d_taskno())
229 if (bp_test_log_only && bp_test_log_only())
232 && bp_test_break(&error_buffer.cpu(cpu)))
243 Jdb::handle_nested_trap(Jdb_entry_frame *e)
245 printf("Trap in JDB: IP:%08lx\n", e->ip());
250 Jdb::handle_conditional_breakpoint(Cpu_number, Jdb_entry_frame *)
256 Jdb::translate_task(Address /*addr*/, Space *task)
258 // we have no idea if addr belongs to kernel or user space
259 // since kernel and user occupy different address spaces
265 Jdb::virt_to_kvirt(Address virt, Mem_space* space)
267 Mem_space::Phys_addr phys;
268 Mem_space::Page_order size;
273 // We can directly access it via virtual addresses if it's kernel code
274 // (which is always mapped, but doesn't appear in the kernel pagetable)
275 // or if we find a mapping for it in the kernel's master pagetable.
276 return (virt >= (Address)&Mem_layout::load &&
277 virt < (Kernel_thread::init_done()
278 ? (Address)&Mem_layout::end
279 : (Address)&Mem_layout::initcall_end)
280 || (Kernel_task::kernel_task()->virt_to_phys(virt) != ~0UL))
287 // We can't directly access it because it's in a different host process
288 // but if the task's pagetable has a mapping for it, we can translate
289 // task-virtual -> physical -> kernel-virtual address and then access.
291 return (space->v_lookup(va, &phys, &size, 0))
292 ? (Address) Kmem::phys_to_virt(Mem_space::Phys_addr::val(phys) + Virt_size::val(cxx::get_lsb(va, size)))
297 IMPLEMENT inline NEEDS ["space.h"]
298 template <typename T>
300 Jdb::peek (T const *addr, Address_type user)
302 // FIXME: assume UP here (current_meme_space(0))
303 return Mem_space::current_mem_space(Cpu_number::boot_cpu())->peek(addr, user);
308 Jdb::peek_task(Address virt, Space *space, void *value, int width)
310 // make sure we don't cross a page boundary
311 if (virt & (width-1))
314 Address kvirt = virt_to_kvirt(virt, space);
315 if (kvirt == (Address)-1)
318 memcpy(value, (void*)kvirt, width);
324 Jdb::poke_task(Address virt, Space *space, void const *value, int width)
326 // make sure we don't cross a page boundary
327 if (virt & (width-1))
330 Address kvirt = virt_to_kvirt(virt, space);
332 if (kvirt == (Address)-1)
335 memcpy((void*)kvirt, value, width);
341 Jdb::is_adapter_memory(Address /*addr*/, Space * /*task*/)
346 #define WEAK __attribute__((weak))
347 extern "C" char in_slowtrap, in_page_fault, in_handle_fputrap;
348 extern "C" char in_interrupt, in_timer_interrupt, in_timer_interrupt_slow;
349 extern "C" char i30_ret_switch WEAK, in_slow_ipc1 WEAK;
350 extern "C" char in_slow_ipc2 WEAK, in_slow_ipc4;
351 extern "C" char in_sc_ipc1 WEAK, in_sc_ipc2 WEAK, in_syscall WEAK;
354 /** Try to guess the thread state of t by walking down the kernel stack and
355 * locking at the first return address we find. */
357 static Jdb::Guessed_thread_state
358 Jdb::guess_thread_state(Thread *t)
360 Guessed_thread_state state = s_unknown;
361 Mword *ktop = (Mword*)((Mword)context_of(t->get_kernel_sp()) +
364 for (int i=-1; i>-26; i--)
368 if (ktop[i] == (Mword)&in_page_fault)
370 if ((ktop[i] == (Mword)&i30_ret_switch) ||// shortcut.S, int 0x30
371 (ktop[i] == (Mword)&in_slow_ipc1) || // shortcut.S, int 0x30
372 (ktop[i] == (Mword)&in_slow_ipc4) || // entry.S, int 0x30
373 #if !defined(CONFIG_ASSEMBLER_IPC_SHORTCUT)
374 (ktop[i] == (Mword)&in_sc_ipc1) || // entry.S, int 0x30
375 (ktop[i] == (Mword)&in_sc_ipc2) || // entry.S, sysenter
379 else if (ktop[i] == (Mword)&in_syscall)
381 else if (ktop[i] == (Mword)&Thread::user_invoke)
382 state = s_user_invoke;
383 else if (ktop[i] == (Mword)&in_handle_fputrap)
385 else if (ktop[i] == (Mword)&in_interrupt)
387 else if ((ktop[i] == (Mword)&in_timer_interrupt) ||
388 (ktop[i] == (Mword)&in_timer_interrupt_slow))
389 state = s_timer_interrupt;
390 else if (ktop[i] == (Mword)&in_slowtrap)
392 if (state != s_unknown)
397 if (state == s_unknown && (t->state() & Thread_ipc_mask))
403 // Don't make these members of Jdb else we have to include <termios.h>
404 // into the Jdb interface ...
405 static struct termios raw, new_raw;
406 static int getchar_entered;
408 /** prepare Linux console for raw input */
413 if (!getchar_entered++)
415 tcgetattr (fileno (stdin), &raw);
416 memcpy(&new_raw, &raw, sizeof(new_raw));
417 new_raw.c_lflag &= ~(ICANON|ECHO);
418 new_raw.c_cc[VMIN] = 0;
419 new_raw.c_cc[VTIME] = 1;
420 tcsetattr (fileno (stdin), TCSAFLUSH, &new_raw);
424 /** restore Linux console. */
429 if (!--getchar_entered)
430 tcsetattr (fileno (stdin), TCSAFLUSH, &raw);
433 //----------------------------------------------------------------------------
434 IMPLEMENTATION [ux && mp]:
438 Jdb::send_nmi(Cpu_number)