Use NMIs to halt all cores when entering the debugger and resume all cores on exit.
This commit is contained in:
parent
4a77cebdb4
commit
33af1ed42b
@ -9,20 +9,73 @@
|
|||||||
|
|
||||||
#include <machine/amd64.h>
|
#include <machine/amd64.h>
|
||||||
#include <machine/amd64op.h>
|
#include <machine/amd64op.h>
|
||||||
|
#include <machine/atomic.h>
|
||||||
#include <machine/trap.h>
|
#include <machine/trap.h>
|
||||||
|
#include <machine/lapic.h>
|
||||||
|
#include <machine/mp.h>
|
||||||
|
|
||||||
TrapFrame *frames[MAX_CPUS];
|
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;
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
MP_SetState(CPUSTATE_HALTED);
|
||||||
|
__sync_fetch_and_add(&debugHalted, 1);
|
||||||
|
|
||||||
|
while (debugCmd == 0) {
|
||||||
|
pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
__sync_fetch_and_sub(&debugHalted, 1);
|
||||||
|
MP_SetState(CPUSTATE_BOOTED);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Debug_Breakpoint(TrapFrame *tf)
|
Debug_Breakpoint(TrapFrame *tf)
|
||||||
{
|
{
|
||||||
frames[CPU()] = tf;
|
frames[CPU()] = tf;
|
||||||
|
|
||||||
// Stop all processors
|
// Should probably force all cores into the debugger
|
||||||
|
while(atomic_swap_uint64(&debugLock, 1) == 1) {
|
||||||
|
// Wait to acquire debugger lock
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop all processors
|
||||||
|
Debug_HaltCPUs();
|
||||||
|
|
||||||
|
// Enter prompt
|
||||||
Debug_Prompt();
|
Debug_Prompt();
|
||||||
|
|
||||||
// Resume all processors
|
// Resume all processors
|
||||||
|
Debug_ResumeCPUs();
|
||||||
|
atomic_set_uint64(&debugLock, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -10,6 +10,7 @@ uint32_t LAPIC_CPU();
|
|||||||
void LAPIC_SendEOI();
|
void LAPIC_SendEOI();
|
||||||
void LAPIC_StartAP(uint8_t apicid, uint32_t addr);
|
void LAPIC_StartAP(uint8_t apicid, uint32_t addr);
|
||||||
int LAPIC_Broadcast(int vector);
|
int LAPIC_Broadcast(int vector);
|
||||||
|
int LAPIC_BroadcastNMI(int vector);
|
||||||
void LAPIC_Periodic(uint64_t rate);
|
void LAPIC_Periodic(uint64_t rate);
|
||||||
|
|
||||||
#endif /* __LAPIC_H__ */
|
#endif /* __LAPIC_H__ */
|
||||||
|
@ -2,8 +2,15 @@
|
|||||||
#ifndef __MACHINE_MP_H__
|
#ifndef __MACHINE_MP_H__
|
||||||
#define __MACHINE_MP_H__
|
#define __MACHINE_MP_H__
|
||||||
|
|
||||||
|
#define CPUSTATE_NOT_PRESENT 0
|
||||||
|
#define CPUSTATE_BOOTED 1
|
||||||
|
#define CPUSTATE_HALTED 2
|
||||||
|
#define CPUSTATE_MAX 2
|
||||||
|
|
||||||
void MP_Init();
|
void MP_Init();
|
||||||
void MP_InitAP();
|
void MP_InitAP();
|
||||||
|
void MP_SetState(int state);
|
||||||
|
int MP_GetCPUs();
|
||||||
|
|
||||||
/* Cross Calls */
|
/* Cross Calls */
|
||||||
typedef int (*CrossCallCB)(void *);
|
typedef int (*CrossCallCB)(void *);
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
#define T_SYSCALL 60 /* System Call */
|
#define T_SYSCALL 60 /* System Call */
|
||||||
#define T_CROSSCALL 61 /* Cross Call (IPI) */
|
#define T_CROSSCALL 61 /* Cross Call (IPI) */
|
||||||
|
#define T_DEBUGIPI 62 /* Kernel Debugger Halt (IPI */
|
||||||
|
|
||||||
#define T_UNKNOWN 63 /* Unknown Trap */
|
#define T_UNKNOWN 63 /* Unknown Trap */
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#define LAPIC_ICR_LO 0x0300 /* Interrupt Command Register */
|
#define LAPIC_ICR_LO 0x0300 /* Interrupt Command Register */
|
||||||
#define LAPIC_ICR_HI 0x0310 /* Interrupt Command Register */
|
#define LAPIC_ICR_HI 0x0310 /* Interrupt Command Register */
|
||||||
#define LAPIC_ICR_FIXED 0x0000 /* Delivery Mode */
|
#define LAPIC_ICR_FIXED 0x0000 /* Delivery Mode */
|
||||||
|
#define LAPIC_ICR_NMI 0x0400
|
||||||
#define LAPIC_ICR_INIT 0x0500
|
#define LAPIC_ICR_INIT 0x0500
|
||||||
#define LAPIC_ICR_STARTUP 0x0600
|
#define LAPIC_ICR_STARTUP 0x0600
|
||||||
#define LAPIC_ICR_ASSERT 0x4000
|
#define LAPIC_ICR_ASSERT 0x4000
|
||||||
@ -156,6 +157,24 @@ LAPIC_Broadcast(int vector)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
LAPIC_BroadcastNMI(int vector)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
LAPIC_Write(LAPIC_ICR_LO, LAPIC_ICR_EXCSELF | LAPIC_ICR_NMI | vector);
|
||||||
|
|
||||||
|
while ((LAPIC_Read(LAPIC_ICR_LO) & LAPIC_ICR_DELIVERY_PENDING) != 0) {
|
||||||
|
pause();
|
||||||
|
|
||||||
|
if (i > 1000000) {
|
||||||
|
kprintf("IPI not delivered?\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LAPIC_Init()
|
LAPIC_Init()
|
||||||
{
|
{
|
||||||
|
@ -32,8 +32,11 @@ typedef struct CrossCallFrame {
|
|||||||
volatile int status[MAX_CPUS];
|
volatile int status[MAX_CPUS];
|
||||||
} CrossCallFrame;
|
} CrossCallFrame;
|
||||||
|
|
||||||
#define CPUSTATE_NOT_PRESENT 0
|
const char *CPUStateToString[] = {
|
||||||
#define CPUSTATE_BOOTED 1
|
"NOT PRESENT",
|
||||||
|
"BOOTED",
|
||||||
|
"HALTED",
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct CPUState {
|
typedef struct CPUState {
|
||||||
int state;
|
int state;
|
||||||
@ -83,6 +86,7 @@ MPBootAP(int procNo)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MP_Init()
|
MP_Init()
|
||||||
{
|
{
|
||||||
@ -118,6 +122,19 @@ MP_InitAP()
|
|||||||
booted = 1;
|
booted = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MP_SetState(int state)
|
||||||
|
{
|
||||||
|
ASSERT(state > 0 && state <= CPUSTATE_MAX);
|
||||||
|
cpus[CPU()].state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
MP_GetCPUs()
|
||||||
|
{
|
||||||
|
return lastCPU;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MP_CrossCallTrap()
|
MP_CrossCallTrap()
|
||||||
{
|
{
|
||||||
@ -217,7 +234,7 @@ Debug_CPUS(int argc, const char *argv[])
|
|||||||
|
|
||||||
for (c = 0; c < MAX_CPUS; c++) {
|
for (c = 0; c < MAX_CPUS; c++) {
|
||||||
if (cpus[c].state != CPUSTATE_NOT_PRESENT) {
|
if (cpus[c].state != CPUSTATE_NOT_PRESENT) {
|
||||||
kprintf("CPU %d: BOOTED\n", c);
|
kprintf("CPU %d: %s\n", c, CPUStateToString[cpus[c].state]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
extern uint64_t trap_table[T_MAX];
|
extern uint64_t trap_table[T_MAX];
|
||||||
extern void trap_pop(TrapFrame *tf);
|
extern void trap_pop(TrapFrame *tf);
|
||||||
extern void Debug_Breakpoint(TrapFrame *tf);
|
extern void Debug_Breakpoint(TrapFrame *tf);
|
||||||
|
extern void Debug_HaltIPI(TrapFrame *tf);
|
||||||
extern void KTimer_Process();
|
extern void KTimer_Process();
|
||||||
|
|
||||||
static InteruptGate64 idt[256];
|
static InteruptGate64 idt[256];
|
||||||
@ -147,12 +148,18 @@ trap_entry(TrapFrame *tf)
|
|||||||
// XXX: USE ATOMIC!
|
// XXX: USE ATOMIC!
|
||||||
intStats[tf->vector]++;
|
intStats[tf->vector]++;
|
||||||
|
|
||||||
|
// Debug NMI (should be T_DEBUGIPI)
|
||||||
|
if (tf->vector == T_NMI) {
|
||||||
|
Debug_HaltIPI(tf);
|
||||||
|
LAPIC_SendEOI();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Kernel
|
// Kernel
|
||||||
if (tf->cs == SEL_KCS)
|
if (tf->cs == SEL_KCS)
|
||||||
{
|
{
|
||||||
// Kernel Debugger
|
// Kernel Debugger
|
||||||
if (tf->vector == T_BP || tf->vector == T_DE)
|
if (tf->vector == T_BP || tf->vector == T_DE) {
|
||||||
{
|
|
||||||
Debug_Breakpoint(tf);
|
Debug_Breakpoint(tf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -251,6 +251,7 @@ Debug_Prompt()
|
|||||||
char *argv[DEBUG_MAX_ARGS];
|
char *argv[DEBUG_MAX_ARGS];
|
||||||
char *nextArg;
|
char *nextArg;
|
||||||
char buf[DEBUG_MAX_LINE];
|
char buf[DEBUG_MAX_LINE];
|
||||||
|
|
||||||
kprintf("Entered Debugger!\n");
|
kprintf("Entered Debugger!\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user