6 static int (*bp_test_log_only)(Cpu_number);
7 static int (*bp_test_break)(Cpu_number, String_buffer *);
13 #include "kernel_task.h"
14 #include "kmem_alloc.h"
15 #include "kmem_space.h"
17 #include "mem_layout.h"
19 #include "static_init.h"
20 #include "timer_tick.h"
22 #include "cxx/cxx_int"
24 STATIC_INITIALIZE_P(Jdb, JDB_INIT_PRIO);
26 DEFINE_PER_CPU static Per_cpu<Proc::Status> jdb_irq_state;
28 int (*Jdb::bp_test_log_only)(Cpu_number);
29 int (*Jdb::bp_test_break)(Cpu_number, String_buffer *buf);
31 // ------------------------------------------------------------------------
32 IMPLEMENTATION [arm && !pic_gic]:
44 // ------------------------------------------------------------------------
45 IMPLEMENTATION [arm && pic_gic]:
51 unsigned orig_tt_prio;
54 static Jdb_wfi_gic wfi_gic;
60 Jdb_core::wait_for_input = _wait_for_input;
62 Timer_tick *tt = Timer_tick::boot_cpu_timer_tick();
63 Gic *g = static_cast<Gic*>(tt->chip());
65 wfi_gic.orig_tt_prio = g->irq_prio(tt->pin());
66 wfi_gic.orig_pmr = g->pmr();
68 g->irq_prio(tt->pin(), 0x10);
70 Timer_tick::enable(Cpu_number::boot_cpu());
77 Timer_tick *tt = Timer_tick::boot_cpu_timer_tick();
78 Gic *g = static_cast<Gic*>(tt->chip());
79 g->irq_prio(tt->pin(), wfi_gic.orig_tt_prio);
80 g->pmr(wfi_gic.orig_pmr);
85 Jdb::_wait_for_input()
89 Timer_tick *tt = Timer_tick::boot_cpu_timer_tick();
90 unsigned i = static_cast<Gic*>(tt->chip())->pending();
97 printf("JDB: Unexpected interrupt %d\n", i);
100 // ------------------------------------------------------------------------
101 IMPLEMENTATION [arm]:
103 // disable interrupts before entering the kernel debugger
106 Jdb::save_disable_irqs(Cpu_number cpu)
108 jdb_irq_state.cpu(cpu) = Proc::cli_save();
109 if (cpu == Cpu_number::boot_cpu())
112 Timer_tick::disable(cpu);
114 if (cpu == Cpu_number::boot_cpu())
118 // restore interrupts after leaving the kernel debugger
121 Jdb::restore_irqs(Cpu_number cpu)
123 if (cpu == Cpu_number::boot_cpu())
126 Timer_tick::enable(cpu);
128 if (cpu == Cpu_number::boot_cpu())
130 Proc::sti_restore(jdb_irq_state.cpu(cpu));
135 Jdb::enter_trap_handler(Cpu_number)
140 Jdb::leave_trap_handler(Cpu_number)
145 Jdb::handle_conditional_breakpoint(Cpu_number cpu, Jdb_entry_frame *e)
147 return Thread::is_debug_exception(e->error_code)
148 && bp_test_log_only && bp_test_log_only(cpu);
153 Jdb::handle_nested_trap(Jdb_entry_frame *e)
155 printf("Trap in JDB: IP:%08lx PSR=%08lx ERR=%08lx\n",
156 e->ip(), e->psr, e->error_code);
161 Jdb::handle_debug_traps(Cpu_number cpu)
163 Jdb_entry_frame *ef = entry_frame.cpu(cpu);
164 error_buffer.cpu(cpu).clear();
166 if (Thread::is_debug_exception(ef->error_code)
168 return bp_test_break(cpu, &error_buffer.cpu(cpu));
170 if (ef->error_code == (0x33UL << 26))
171 error_buffer.cpu(cpu).printf("%s",(char const *)ef->r[0]);
172 else if (ef->debug_ipi())
173 error_buffer.cpu(cpu).printf("IPI ENTRY");
175 error_buffer.cpu(cpu).printf("ENTRY");
182 Jdb::handle_user_request(Cpu_number cpu)
184 Jdb_entry_frame *ef = Jdb::entry_frame.cpu(cpu);
185 const char *str = (char const *)ef->r[0];
186 Space * task = get_task(cpu);
190 return cpu != Cpu_number::boot_cpu();
192 if (ef->error_code == ((0x33UL << 26) | 1))
193 return execute_command_ni(task, str);
195 if (!peek(str, task, tmp) || tmp != '*')
197 if (!peek(str+1, task, tmp) || tmp != '#')
200 return execute_command_ni(task, str+2);
205 Jdb::test_checksums()
210 Jdb::handle_special_cmds(int)
214 FIASCO_INIT FIASCO_NOINLINE void
217 static Jdb_handler enter(at_jdb_enter);
218 static Jdb_handler leave(at_jdb_leave);
220 Jdb::jdb_enter.add(&enter);
221 Jdb::jdb_leave.add(&leave);
223 Thread::nested_trap_handler = (Trap_state::Handler)enter_jdb;
225 Kconsole::console()->register_console(push_cons());
231 Jdb::access_mem_task(Address virt, Space * task)
240 if (Mem_layout::in_kernel(virt))
242 auto p = Kmem_space::kdir()->walk(Virt_addr(virt));
246 phys = p.page_addr() | cxx::get_lsb(virt, p.page_order());
253 phys = Address(task->virt_to_phys(virt));
256 if (phys == (Address)-1)
257 phys = task->virt_to_phys_s0((void *)virt);
259 if (phys == (Address)-1)
263 unsigned long addr = Mem_layout::phys_to_pmem(phys);
264 if (addr == (Address)-1)
266 Mem_unit::flush_vdcache();
267 auto pte = Kmem_space::kdir()
268 ->walk(Virt_addr(Mem_layout::Jdb_tmp_map_area), Pdir::Super_level);
270 if (!pte.is_valid() || pte.page_addr() != cxx::mask_lsb(phys, pte.page_order()))
272 pte.create_page(Phys_mem_addr(cxx::mask_lsb(phys, pte.page_order())),
273 Page::Attr(Page::Rights::RW()));
274 pte.write_back_if(true, Mem_unit::Asid_kernel);
277 Mem_unit::kernel_tlb_flush();
279 addr = Mem_layout::Jdb_tmp_map_area + (phys & (Config::SUPERPAGE_SIZE - 1));
287 Jdb::translate_task(Address addr, Space * task)
289 return (Kmem::is_kmem_page_fault(addr, 0)) ? 0 : task;
294 Jdb::peek_task(Address virt, Space * task, void *value, int width)
296 void const *mem = access_mem_task(virt, task);
304 Mword dealign = (virt & 0x3) * 8;
305 *(Mword*)value = (*(Mword*)mem & (0xff << dealign)) >> dealign;
310 Mword dealign = ((virt & 0x2) >> 1) * 16;
311 *(Mword*)value = (*(Mword*)mem & (0xffff << dealign)) >> dealign;
315 memcpy(value, mem, width);
323 Jdb::is_adapter_memory(Address, Space *)
330 Jdb::poke_task(Address virt, Space * task, void const *val, int width)
332 void *mem = access_mem_task(virt, task);
336 memcpy(mem, val, width);
345 Mem_unit::clean_vdcache();
352 Mem_unit::flush_vcache();
367 Jdb::write_tsc_s(String_buffer *buf, Signed64 tsc, bool sign)
370 buf->printf("%c", (tsc < 0) ? '-' : (tsc == 0) ? ' ' : '+');
371 buf->printf("%lld c", tsc);
376 Jdb::write_tsc(String_buffer *buf, Signed64 tsc, bool sign)
378 write_tsc_s(buf, tsc, sign);
382 //----------------------------------------------------------------------------
383 IMPLEMENTATION [arm && mp]:
389 Jdb::send_nmi(Cpu_number cpu)
391 printf("NMI to %d, what's that?\n",
392 cxx::int_value<Cpu_number>(cpu));
395 IMPLEMENT_OVERRIDE inline template< typename T >
397 Jdb::set_monitored_address(T *dest, T val)
399 *const_cast<T volatile *>(dest) = val;
404 IMPLEMENT_OVERRIDE inline template< typename T >
406 Jdb::monitor_address(Cpu_number, T volatile const *addr)