182 lines
3.3 KiB
C
182 lines
3.3 KiB
C
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdatomic.h>
|
|
|
|
#include <sys/kassert.h>
|
|
#include <sys/kconfig.h>
|
|
#include <sys/kdebug.h>
|
|
#include <sys/mp.h>
|
|
|
|
#include <machine/cpu.h>
|
|
#include <machine/cpuop.h>
|
|
#include <machine/trap.h>
|
|
#include <machine/mp.h>
|
|
|
|
TrapFrame *frames[MAX_CPUS];
|
|
|
|
volatile static uint64_t debugLock = 0;
|
|
volatile static uint64_t debugCmd = 0;
|
|
volatile static uint64_t debugHalted = 0;
|
|
|
|
void
|
|
Debug_HaltCPUs()
|
|
{
|
|
debugCmd = 0;
|
|
|
|
//if (MP_GetCPUs() == 1)
|
|
return;
|
|
|
|
//LAPIC_BroadcastNMI(T_DEBUGIPI);
|
|
|
|
// Wait for processors to enter
|
|
/*while (debugHalted < (MP_GetCPUs() - 1)) {
|
|
pause();
|
|
}*/
|
|
}
|
|
|
|
void
|
|
Debug_ResumeCPUs()
|
|
{
|
|
debugCmd = 1;
|
|
|
|
// Wait for processors to resume
|
|
while (debugHalted > 0) {
|
|
pause();
|
|
}
|
|
}
|
|
|
|
void
|
|
Debug_HaltIPI(TrapFrame *tf)
|
|
{
|
|
MP_GetCPUState()->state = CPUSTATE_HALTED;
|
|
atomic_fetch_add(&debugHalted, 1);
|
|
|
|
frames[CPU()] = tf;
|
|
|
|
while (debugCmd == 0) {
|
|
pause();
|
|
}
|
|
|
|
atomic_fetch_sub(&debugHalted, 1);
|
|
MP_GetCPUState()->state = CPUSTATE_BOOTED;
|
|
}
|
|
|
|
void
|
|
Debug_Breakpoint(TrapFrame *tf)
|
|
{
|
|
frames[CPU()] = tf;
|
|
|
|
// Should probably force all cores into the debugger
|
|
while(atomic_exchange(&debugLock, 1) == 1) {
|
|
// Wait to acquire debugger lock
|
|
}
|
|
|
|
// Stop all processors
|
|
Debug_HaltCPUs();
|
|
|
|
// Enter prompt
|
|
Debug_Prompt();
|
|
|
|
// Resume all processors
|
|
Debug_ResumeCPUs();
|
|
atomic_store(&debugLock, 0);
|
|
}
|
|
|
|
static void
|
|
Debug_Registers(int argc, const char *argv[])
|
|
{
|
|
UNUSED TrapFrame *tf = frames[CPU()];
|
|
|
|
if (argc == 2) {
|
|
int cpuNo = Debug_StrToInt(argv[1]);
|
|
if (cpuNo >= MAX_CPUS) {
|
|
kprintf("Invalid CPU number\n");
|
|
return;
|
|
}
|
|
tf = frames[cpuNo];
|
|
}
|
|
|
|
}
|
|
|
|
REGISTER_DBGCMD(registers, "Show CPU registers", Debug_Registers);
|
|
|
|
static void
|
|
Debug_Backtrace(int argc, const char *argv[])
|
|
{
|
|
UNUSED TrapFrame *tf = frames[CPU()];
|
|
uint64_t *ptr;
|
|
uint64_t rip;
|
|
uint64_t rbp;
|
|
|
|
if (argc == 2) {
|
|
int cpuNo = Debug_StrToInt(argv[1]);
|
|
if (cpuNo >= MAX_CPUS) {
|
|
kprintf("Invalid CPU number\n");
|
|
return;
|
|
}
|
|
tf = frames[cpuNo];
|
|
}
|
|
|
|
rip = 0; //tf->rip;
|
|
rbp = 0; //tf->rbp;
|
|
|
|
kprintf("%-16s %-16s\n", "IP Pointer", "Base Pointer");
|
|
while (3) {
|
|
kprintf("%016lx %016lx\n", rip, rbp);
|
|
ptr = (uint64_t *)rbp;
|
|
if (rbp == 0ULL || rip == 0ULL) {
|
|
break;
|
|
}
|
|
rbp = ptr[0];
|
|
rip = ptr[1];
|
|
}
|
|
}
|
|
|
|
REGISTER_DBGCMD(backtrace, "Print backtrace", Debug_Backtrace);
|
|
|
|
static void
|
|
Debug_SetBreakpoint(int argc, const char *argv[])
|
|
{
|
|
if (argc != 2) {
|
|
kprintf("bkpt [ADDR]");
|
|
return;
|
|
}
|
|
|
|
UNUSED uint64_t addr = Debug_StrToInt(argv[1]);
|
|
|
|
kprintf("NOT IMPLEMENTED\n");
|
|
}
|
|
|
|
REGISTER_DBGCMD(bkpt, "Set breakpoint", Debug_SetBreakpoint);
|
|
|
|
static void
|
|
Debug_ClearBreakpoint(int argc, UNUSED const char *argv[])
|
|
{
|
|
if (argc != 2) {
|
|
kprintf("clrbkpt [0-3]");
|
|
return;
|
|
}
|
|
|
|
kprintf("NOT IMPLEMENTED\n");
|
|
}
|
|
|
|
REGISTER_DBGCMD(clrbkpt, "Clear breakpoint", Debug_ClearBreakpoint);
|
|
|
|
static void
|
|
Debug_ListBreakpoints(UNUSED int argc, UNUSED const char *argv[])
|
|
{
|
|
kprintf("NOT IMPLEMENTED\n");
|
|
}
|
|
|
|
REGISTER_DBGCMD(bkpts, "List breakpoint", Debug_ListBreakpoints);
|
|
|
|
static void
|
|
Debug_Reboot(UNUSED int argc, UNUSED const char *argv[])
|
|
{
|
|
kprintf("NOT IMPLEMENTED\n");
|
|
}
|
|
|
|
REGISTER_DBGCMD(reboot, "Reboot computer", Debug_Reboot);
|
|
|