static void init();
static Per_cpu<unsigned> apic_tpr;
- static Pic::Status pic_status;
+ static Unsigned16 pic_status;
static volatile char msr_test;
static volatile char msr_fail;
static int (*bp_test_log_only)();
static int (*bp_test_sstep)();
- static int (*bp_test_break)(char *errbuf, size_t bufsize);
- static int (*bp_test_other)(char *errbuf, size_t bufsize);
+ static int (*bp_test_break)(String_buffer *buf);
+ static int (*bp_test_other)(String_buffer *buf);
private:
#include "apic.h"
#include "boot_info.h"
#include "checksum.h"
-#include "cmdline.h"
#include "config.h"
#include "cpu.h"
#include "initcalls.h"
#include "kernel_uart.h"
#include "kernel_task.h"
#include "kmem.h"
+#include "koptions.h"
#include "logdefs.h"
#include "mem_layout.h"
#include "pic.h"
#include "regdefs.h"
#include "static_init.h"
#include "terminate.h"
-#include "thread.h"
+#include "thread.h"
#include "thread_state.h"
#include "timer.h"
+#include "timer_tick.h"
#include "trap_state.h"
-#include "virq.h"
#include "vkey.h"
#include "watchdog.h"
char Jdb::_connected; // Jdb::init() was done
// explicit single_step command
-Per_cpu<char> DEFINE_PER_CPU Jdb::permanent_single_step;
+DEFINE_PER_CPU Per_cpu<char> Jdb::permanent_single_step;
volatile char Jdb::msr_test; // = 1: trying to access an msr
volatile char Jdb::msr_fail; // = 1: MSR access failed
-Per_cpu<char> DEFINE_PER_CPU Jdb::code_ret; // current instruction is ret/iret
-Per_cpu<char> DEFINE_PER_CPU Jdb::code_call;// current instruction is call
-Per_cpu<char> DEFINE_PER_CPU Jdb::code_bra; // current instruction is jmp/jxx
-Per_cpu<char> DEFINE_PER_CPU Jdb::code_int; // current instruction is int x
+DEFINE_PER_CPU Per_cpu<char> Jdb::code_ret; // current instruction is ret/iret
+DEFINE_PER_CPU Per_cpu<char> Jdb::code_call;// current instruction is call
+DEFINE_PER_CPU Per_cpu<char> Jdb::code_bra; // current instruction is jmp/jxx
+DEFINE_PER_CPU Per_cpu<char> Jdb::code_int; // current instruction is int x
// special single step state
-Per_cpu<Jdb::Step_state> DEFINE_PER_CPU Jdb::ss_state;
-Per_cpu<int> DEFINE_PER_CPU Jdb::ss_level; // current call level
+DEFINE_PER_CPU Per_cpu<Jdb::Step_state> Jdb::ss_state;
+DEFINE_PER_CPU Per_cpu<int> Jdb::ss_level; // current call level
const Unsigned8*Jdb::debug_ctrl_str; // string+length for remote control of
int Jdb::debug_ctrl_len; // Jdb via enter_kdebugger("*#");
-Pic::Status Jdb::pic_status;
-Per_cpu<unsigned> DEFINE_PER_CPU Jdb::apic_tpr;
-Per_cpu<int> DEFINE_PER_CPU Jdb::jdb_irqs_disabled;
+Unsigned16 Jdb::pic_status;
+DEFINE_PER_CPU Per_cpu<unsigned> Jdb::apic_tpr;
+DEFINE_PER_CPU Per_cpu<int> Jdb::jdb_irqs_disabled;
int (*Jdb::bp_test_log_only)();
int (*Jdb::bp_test_sstep)();
-int (*Jdb::bp_test_break)(char *errbuf, size_t bufsize);
-int (*Jdb::bp_test_other)(char *errbuf, size_t bufsize);
+int (*Jdb::bp_test_break)(String_buffer *buf);
+int (*Jdb::bp_test_other)(String_buffer *buf);
// available from the jdb_dump module
int jdb_dump_addr_task (Address addr, Space *task, int level)
IMPLEMENT FIASCO_INIT FIASCO_NOINLINE
void Jdb::init()
{
- if (strstr (Cmdline::cmdline(), " -nojdb"))
+ if (Koptions::o()->opt(Koptions::F_nojdb))
return;
- if (strstr (Cmdline::cmdline(), " -jdb_never_stop"))
+ if (Koptions::o()->opt(Koptions::F_jdb_never_stop))
never_break = 1;
init_serial_console();
return _connected;
}
-PROTECTED static inline
-void
-Jdb::monitor_address(unsigned current_cpu, void *addr)
+IMPLEMENT_OVERRIDE inline template< typename T >
+T
+Jdb::monitor_address(Cpu_number current_cpu, T volatile const *addr)
{
- if (Cpu::cpus.cpu(current_cpu).has_monitor_mwait())
+ if (!*addr && Cpu::cpus.cpu(current_cpu).has_monitor_mwait())
{
asm volatile ("monitor \n" : : "a"(addr), "c"(0), "d"(0) );
Mword irq_sup = Cpu::cpus.cpu(current_cpu).has_monitor_mwait_irq() ? 1 : 0;
asm volatile ("mwait \n" : : "a"(0x00), "c"(irq_sup) );
}
-}
-
-#if 0
-PUBLIC static
-template <typename T> T
-Jdb::peek(T const *addr)
-{
return *addr;
}
-PUBLIC static
-template <typename T> T
-Jdb::peek(T const *addr, Address_type)
-{
- // on IA32 we can touch directly into the user-space
- return *(T*)addr;
-}
-#endif
static inline
void
}
-static Per_cpu<Proc::Status> DEFINE_PER_CPU jdb_saved_flags;
+DEFINE_PER_CPU static Per_cpu<Proc::Status> jdb_saved_flags;
// disable interrupts before entering the kernel debugger
IMPLEMENT
void
-Jdb::save_disable_irqs(unsigned cpu)
+Jdb::save_disable_irqs(Cpu_number cpu)
{
if (!jdb_irqs_disabled.cpu(cpu)++)
{
// save interrupt flags
jdb_saved_flags.cpu(cpu) = Proc::cli_save();
- if (cpu == 0)
+ if (cpu == Cpu_number::boot_cpu())
{
Watchdog::disable();
pic_status = Pic::disable_all_save();
+ if (Config::getchar_does_hlt_works_ok)
+ Timer_tick::disable(Cpu_number::boot_cpu());
}
if (Io_apic::active() && Apic::is_present())
{
apic_tpr.cpu(cpu) = Apic::tpr();
- Apic::tpr(APIC_IRQ_BASE - 0x10);
+ Apic::tpr(APIC_IRQ_BASE - 0x08);
}
-
- if (cpu == 0 && Config::getchar_does_hlt && Config::getchar_does_hlt_works_ok)
+
+ if (cpu == Cpu_number::boot_cpu() && Config::getchar_does_hlt_works_ok)
{
// set timer interrupt does nothing than wakeup from hlt
- Idt::set_vectors_stop();
- Timer::enable();
+ Timer_tick::set_vectors_stop();
+ Timer_tick::enable(Cpu_number::boot_cpu());
}
}
- if (cpu == 0 && Config::getchar_does_hlt && Config::getchar_does_hlt_works_ok)
+ if (cpu == Cpu_number::boot_cpu() && Config::getchar_does_hlt_works_ok)
// explicit enable interrupts because the timer interrupt is
// needed to wakeup from "hlt" state in getchar(). All other
// interrupts are disabled at the pic.
// restore interrupts after leaving the kernel debugger
IMPLEMENT
void
-Jdb::restore_irqs(unsigned cpu)
+Jdb::restore_irqs(Cpu_number cpu)
{
if (!--jdb_irqs_disabled.cpu(cpu))
{
if (Io_apic::active() && Apic::is_present())
Apic::tpr(apic_tpr.cpu(cpu));
- if (cpu == 0)
+ if (cpu == Cpu_number::boot_cpu())
{
Pic::restore_all(Jdb::pic_status);
Watchdog::enable();
}
// reset timer interrupt vector
- if (cpu == 0 && Config::getchar_does_hlt && Config::getchar_does_hlt_works_ok)
+ if (cpu == Cpu_number::boot_cpu() && Config::getchar_does_hlt_works_ok)
Idt::set_vectors_run();
// reset interrupt flags
}
-PUBLIC
-static int
-Jdb::get_register(char *reg)
-{
- union
- {
- char c[4];
- Unsigned32 v;
- } reg_name;
-
- int i;
-
- putchar(reg_name.c[0] = Jdb_screen::Reg_prefix);
-
- for (i=1; i<3; i++)
- {
- int c = getchar();
- if (c == KEY_ESC)
- return false;
- putchar(reg_name.c[i] = c & 0xdf);
- }
-
- reg_name.c[3] = '\0';
-
- for (i=0; i<9; i++)
- if (reg_name.v == *((unsigned*)(Jdb_screen::Reg_names[i])))
- break;
-
- if (i==9)
- return false;
-
- *reg = i+1;
- return true;
-}
-
struct On_dbg_stack
{
Mword sp;
On_dbg_stack(Mword sp) : sp(sp) {}
- bool operator () (unsigned cpu) const
+ bool operator () (Cpu_number cpu) const
{
Thread::Dbg_stack const &st = Thread::dbg_stack.cpu(cpu);
return sp <= Mword(st.stack_top)
// Do thread lookup using Trap_state. In contrast to Thread::current_thread()
// this function can also handle cases where we entered from kernel stack
// context. We _never_ return 0!
-IMPLEMENT
+IMPLEMENT_OVERRIDE
Thread*
-Jdb::get_thread(unsigned cpu)
+Jdb::get_thread(Cpu_number cpu)
{
Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
Address sp = (Address) entry_frame;
if (foreach_cpu(On_dbg_stack(sp), false))
return 0;
- if (sp >= boot_stack - 8192 && sp <= boot_stack + 8192)
+ if (!Helping_lock::threading_system_active)
return 0;
return static_cast<Thread*>(context_of((const void*)sp));
Address pdbr;
asm volatile ("mov %%cr3, %0" : "=r" (pdbr));
Pdir *kdir = (Pdir*)Mem_layout::phys_to_pmem(pdbr);
- Pdir::Iter i = kdir->walk(Virt_addr(addr));
- if (i.e->valid())
+ auto i = kdir->walk(Virt_addr(addr));
+ if (i.is_valid())
{
memcpy(value, (void*)addr, width);
return 0;
else
{
// user address, use temporary mapping
- phys = Address(task->mem_space()->virt_to_phys (addr));
+ phys = Address(task->virt_to_phys (addr));
if (phys == ~0UL)
- phys = task->mem_space()->virt_to_phys_s0 ((void*)addr);
+ phys = task->virt_to_phys_s0((void*)addr);
if (phys == ~0UL)
return -1;
{
Address phys;
- if (task && Kmem::is_kmem_page_fault(addr, 0))
+ if (!task && Kmem::is_kmem_page_fault(addr, 0))
{
Address pdbr;
asm volatile ("mov %%cr3, %0" : "=r" (pdbr));
Pdir *kdir = (Pdir*)Mem_layout::phys_to_pmem(pdbr);
- Pdir::Iter i = kdir->walk(Virt_addr(addr));
- if (i.e->valid())
+ auto i = kdir->walk(Virt_addr(addr));
+ if (i.is_valid())
{
memcpy((void*)addr, value, width);
return 0;
else
{
// user address, use temporary mapping
- phys = Address(task->mem_space()->virt_to_phys (addr));
+ phys = Address(task->virt_to_phys(addr));
if (phys == ~0UL)
- phys = task->mem_space()->virt_to_phys_s0 ((void*)addr);
+ phys = task->virt_to_phys_s0((void*)addr);
if (phys == ~0UL)
return -1;
phys = Kmem::virt_to_phys((const void*)virt);
else
// user address
- phys = task->mem_space()->virt_to_phys_s0((void*)virt);
+ phys = task->virt_to_phys_s0((void*)virt);
if (phys == ~0UL)
return false;
- Mem_desc *m = Kip::k()->mem_descs();
- Mem_desc *e = m + Kip::k()->num_mem_descs();
- for (; m != e; ++m)
- if (m->type() == Mem_desc::Conventional && !m->is_virtual()
- && m->start() <= phys && m->end() >= phys)
+ for (auto const &m: Kip::k()->mem_descs_a())
+ if (m.type() == Mem_desc::Conventional && !m.is_virtual()
+ && m.start() <= phys && m.end() >= phys)
return false;
return true;
{
Guessed_thread_state state = s_unknown;
Mword *ktop = (Mword*)((Mword)context_of(t->get_kernel_sp()) +
- Config::thread_block_size);
+ Context::Size);
for (int i=-1; i>-26; i--)
{
}
}
- if (state == s_unknown && (t->state() & Thread_ipc_mask))
+ if (state == s_unknown && (t->state(false) & Thread_ipc_mask))
state = s_ipc;
return state;
PUBLIC static
void
-Jdb::set_single_step(unsigned cpu, int on)
+Jdb::set_single_step(Cpu_number cpu, int on)
{
if (on)
entry_frame.cpu(cpu)->flags(entry_frame.cpu(cpu)->flags() | EFLAGS_TF);
// set global indicators code_call, code_ret, code_bra, code_int
// This can fail if the current page is still not mapped
static void
-Jdb::analyze_code(unsigned cpu)
+Jdb::analyze_code(Cpu_number cpu)
{
Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
Space *task = get_task(cpu);
IMPLEMENTATION[amd64]:
static void
-Jdb::analyze_code(unsigned)
+Jdb::analyze_code(Cpu_number)
{}
IMPLEMENTATION[ia32,amd64]:
// entered debugger because of single step trap
static inline NOEXPORT int
-Jdb::handle_single_step(unsigned cpu)
+Jdb::handle_single_step(Cpu_number cpu)
{
int really_break = 1;
analyze_code(cpu);
Cpu const &ccpu = Cpu::cpus.cpu(cpu);
+ error_buffer.cpu(cpu).clear();
// special single_step ('j' command): go until branch/return
if (ss_state.cpu(cpu) != SS_NONE)
{
// condition met
ss_state.cpu(cpu) = SS_NONE;
- snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "Branch/Call");
+ error_buffer.cpu(cpu).printf("%s", "Branch/Call");
}
}
else // (ss_state == SS_NONE)
// regular single_step
- snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "Singlestep");
+ error_buffer.cpu(cpu).printf("%s", "Singlestep");
return really_break;
}
// entered debugger due to debug exception
static inline NOEXPORT int
-Jdb::handle_trap1(unsigned cpu)
+Jdb::handle_trap1(Cpu_number cpu)
{
- // FIXME: currently only on bot cpu
- if (cpu != 0)
+ // FIXME: currently only on boot cpu
+ if (cpu != Cpu_number::boot_cpu())
return 0;
if (bp_test_sstep && bp_test_sstep())
return handle_single_step(cpu);
+ error_buffer.cpu(cpu).clear();
if (bp_test_break
- && bp_test_break(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0))))
+ && bp_test_break(&error_buffer.cpu(cpu)))
return 1;
if (bp_test_other
- && bp_test_other(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0))))
+ && bp_test_other(&error_buffer.cpu(cpu)))
return 1;
return 0;
// entered debugger due to software breakpoint
static inline NOEXPORT int
-Jdb::handle_trap3(unsigned cpu)
+Jdb::handle_trap3(Cpu_number cpu)
{
Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
Space *task = get_task(cpu);
Unsigned8 op;
Unsigned8 len;
- snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "INT 3");
+ error_buffer.cpu(cpu).clear();
+ error_buffer.cpu(cpu).printf("%s", "INT 3");
if ( !peek((Unsigned8*)entry_frame->ip(), task, op)
|| !peek((Unsigned8*)(entry_frame->ip()+1), task, len)
|| op != 0xeb)
ctrl[i] = tmp;
}
ctrl[i] = '\0';
- snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)),
- "invalid ctrl sequence \"%s\"", ctrl);
+ error_buffer.cpu(cpu).clear();
+ error_buffer.cpu(cpu).printf("invalid ctrl sequence \"%s\"", ctrl);
}
}
// enter_kdebugger("...");
{
unsigned i;
len = len < 47 ? len : 47;
- len = len < sizeof(error_buffer.cpu(0))-1
- ? len
- : sizeof(error_buffer.cpu(0))-1;
+ error_buffer.cpu(cpu).clear();
for(i=0; i<len && peek(msg+i, task, buffer[0]); i++)
- error_buffer.cpu(cpu)[i] = buffer[0];
- error_buffer.cpu(cpu)[i]='\0';
+ error_buffer.cpu(cpu).append(buffer[0]);
+ error_buffer.cpu(cpu).terminate();
}
return 1;
// entered debugger due to other exception
static inline NOEXPORT int
-Jdb::handle_trapX(unsigned cpu)
+Jdb::handle_trapX(Cpu_number cpu)
{
- unsigned pos = snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s",
- Cpu::exception_string(entry_frame.cpu(cpu)->_trapno)) + 1;
- if ( pos < sizeof(error_buffer.cpu(0))
- && entry_frame.cpu(cpu)->_trapno >= 10
+ error_buffer.cpu(cpu).clear();
+ error_buffer.cpu(cpu).printf("%s", Cpu::exception_string(entry_frame.cpu(cpu)->_trapno));
+ if ( entry_frame.cpu(cpu)->_trapno >= 10
&& entry_frame.cpu(cpu)->_trapno <= 14)
- snprintf(error_buffer.cpu(cpu)+pos, sizeof(error_buffer.cpu(0))-pos,
- "(ERR="L4_PTR_FMT")", entry_frame.cpu(cpu)->_err);
+ error_buffer.cpu(cpu).printf("(ERR=" L4_PTR_FMT ")", entry_frame.cpu(cpu)->_err);
return 1;
}
*/
IMPLEMENT
bool
-Jdb::handle_user_request(unsigned cpu)
+Jdb::handle_user_request(Cpu_number cpu)
{
Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
+ if (entry_frame->debug_ipi())
+ return cpu != Cpu_number::boot_cpu();
+
if (entry_frame->_trapno == 3)
{
Space *task = get_task(cpu);
IMPLEMENT
void
-Jdb::enter_trap_handler(unsigned cpu)
+Jdb::enter_trap_handler(Cpu_number cpu)
{ Cpu::cpus.cpu(cpu).debugctl_disable(); }
IMPLEMENT
void
-Jdb::leave_trap_handler(unsigned cpu)
+Jdb::leave_trap_handler(Cpu_number cpu)
{ Cpu::cpus.cpu(cpu).debugctl_enable(); }
IMPLEMENT
bool
-Jdb::handle_conditional_breakpoint(unsigned cpu)
-{ return entry_frame.cpu(cpu)->_trapno == 1 && bp_test_log_only && bp_test_log_only(); }
+Jdb::handle_conditional_breakpoint(Cpu_number, Jdb_entry_frame *e)
+{ return e->_trapno == 1 && bp_test_log_only && bp_test_log_only(); }
IMPLEMENT
void
Jdb::handle_nested_trap(Jdb_entry_frame *e)
{
// re-enable interrupts if we need them because they are disabled
- if (Config::getchar_does_hlt && Config::getchar_does_hlt_works_ok)
+ if (Config::getchar_does_hlt_works_ok)
Proc::sti();
switch (e->_trapno)
break;
case 3:
cursor(Jdb_screen::height(), 1);
- printf("\nSoftware breakpoint inside jdb at "L4_PTR_FMT"\n",
+ printf("\nSoftware breakpoint inside jdb at " L4_PTR_FMT "\n",
e->ip()-1);
break;
case 13:
break;
default:
cursor(Jdb_screen::height(), 1);
- printf("\nGeneral Protection (eip="L4_PTR_FMT","
- " err="L4_PTR_FMT") -- jdb bug?\n",
+ printf("\nGeneral Protection (eip=" L4_PTR_FMT ","
+ " err=" L4_PTR_FMT ") -- jdb bug?\n",
e->ip(), e->_err);
break;
}
break;
default:
cursor(Jdb_screen::height(), 1);
- printf("\nInvalid access (trap=%02lx err="L4_PTR_FMT
- " pfa="L4_PTR_FMT" eip="L4_PTR_FMT") "
+ printf("\nInvalid access (trap=%02lx err=" L4_PTR_FMT
+ " pfa=" L4_PTR_FMT " eip=" L4_PTR_FMT ") "
"-- jdb bug?\n",
e->_trapno, e->_err, e->_cr2, e->ip());
break;
IMPLEMENT
bool
-Jdb::handle_debug_traps(unsigned cpu)
+Jdb::handle_debug_traps(Cpu_number cpu)
{
bool really_break = true;
if (really_break)
{
- for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
+ for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
{
if (!Cpu::online(i) || !running.cpu(i))
continue;
Jdb::leave_getchar()
{}
-
//----------------------------------------------------------------------------
IMPLEMENTATION [(ia32 || amd64) && mp]:
static
void
-Jdb::send_nmi(unsigned cpu)
+Jdb::send_nmi(Cpu_number cpu)
{
- Apic::mp_send_ipi(Cpu::cpus.cpu(cpu).phys_id(), 0, Apic::APIC_IPI_NMI);
+ Apic::mp_send_ipi(Apic::apic.cpu(cpu)->apic_id(), 0, Apic::APIC_IPI_NMI);
}