mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 04:36:52 -10:00
powerpc64: give each CPU its own KDB trap stack
Kernel mode program, trace, breakpoint and machine check exceptions go through dbtrap, which saves the registers on trapstk and, if KDB doesn't want the trap, restores them from there and continues with the normal trap handler. There was just one trapstk for all CPUs, so when two of them trapped at the same time they overwrote each other's frame and one of them carried on with the other's registers. DTrace fbt probes are these traps, so a probe on a function that runs on several CPUs at once took the kernel down within seconds. Keep the stack in the pcpu instead. The boot CPU gets a static one, since it's set up before malloc works, the others allocate theirs in cpu_pcpu_init() like the Book-E critical interrupt stack. Approved by: jhibbits MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D60362
This commit is contained in:
1 parent
c4fde87a32
commit
eaaf838e33
5 files changed
+33
-12
No files matched your search
@@ -529,6 +529,20 @@ kdb_cpu_set_singlestep(void)
|
||||
kdb_frame->srr1 |= PSL_SE;
|
||||
}
|
||||
|
||||
#if defined(__powerpc64__) && defined(KDB)
|
||||
/* Stack used by the KDB trap handler (dbtrap) on each CPU. */
|
||||
#define AIM_DBSTACK_SIZE 8192
|
||||
|
||||
/*
|
||||
* Stack for the KDB trap handler on the boot CPU. It is static because the
|
||||
* boot CPU is initialised long before malloc works; APs reach cpu_pcpu_init()
|
||||
* at SI_SUB_CPU and allocate theirs. Sizing a MAXCPU array would reserve
|
||||
* megabytes for CPUs that do not exist.
|
||||
*/
|
||||
static char aim_boot_dbstack[AIM_DBSTACK_SIZE] __aligned(16);
|
||||
static bool aim_boot_dbstack_used;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialise a struct pcpu.
|
||||
*/
|
||||
@@ -536,8 +550,21 @@ void
|
||||
cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
|
||||
{
|
||||
#ifdef __powerpc64__
|
||||
#ifdef KDB
|
||||
char *dbstack;
|
||||
#endif
|
||||
|
||||
/* Copy the SLB contents from the current CPU */
|
||||
memcpy(pcpu->pc_aim.slb, PCPU_GET(aim.slb), sizeof(pcpu->pc_aim.slb));
|
||||
|
||||
#ifdef KDB
|
||||
if (!aim_boot_dbstack_used) {
|
||||
aim_boot_dbstack_used = true;
|
||||
dbstack = aim_boot_dbstack;
|
||||
} else
|
||||
dbstack = malloc(AIM_DBSTACK_SIZE, M_DEVBUF, M_WAITOK);
|
||||
pcpu->pc_aim.dbstack = dbstack + AIM_DBSTACK_SIZE;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -62,13 +62,6 @@ GLOBAL(tmpstk)
|
||||
TOC_ENTRY(tmpstk)
|
||||
TOC_ENTRY(can_wakeup)
|
||||
|
||||
#ifdef KDB
|
||||
#define TRAPSTKSZ 8192 /* 8k trap stack */
|
||||
GLOBAL(trapstk)
|
||||
.space TRAPSTKSZ
|
||||
TOC_ENTRY(trapstk)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Entry point for bootloaders that do not fully implement ELF and start
|
||||
|
||||
@@ -920,10 +920,9 @@ dbtrap:
|
||||
andi. %r1,%r1,0xff00
|
||||
mtsprg3 %r1
|
||||
|
||||
GET_TOCBASE(%r1) /* get new SP */
|
||||
addis %r1,%r1,TOC_REF(trapstk)@ha
|
||||
ld %r1,TOC_REF(trapstk)@l(%r1)
|
||||
addi %r1,%r1,(TRAPSTKSZ-48)
|
||||
GET_CPUINFO(%r1) /* this CPU's trap stack */
|
||||
ld %r1,PC_AIM_DBSTACK(%r1)
|
||||
addi %r1,%r1,-48
|
||||
|
||||
FRAME_SETUP(PC_DBSAVE)
|
||||
/* Call C trap code: */
|
||||
|
||||
@@ -69,7 +69,8 @@ struct pvo_entry;
|
||||
struct pvo_entry *qmap_pvo; \
|
||||
struct mtx qmap_lock; \
|
||||
uint64_t opal_hmi_flags; \
|
||||
char __pad[1337];
|
||||
void *dbstack; /* KDB trap stack top */ \
|
||||
char __pad[1329];
|
||||
|
||||
#ifdef __powerpc64__
|
||||
#define PCPU_MD_AIM_FIELDS PCPU_MD_AIM64_FIELDS
|
||||
|
||||
@@ -114,6 +114,7 @@ ASSYM(PC_KERNSLB, offsetof(struct pcpu, pc_aim.slb));
|
||||
ASSYM(PC_USERSLB, offsetof(struct pcpu, pc_aim.userslb));
|
||||
ASSYM(PC_SLBSAVE, offsetof(struct pcpu, pc_aim.slbsave));
|
||||
ASSYM(PC_SLBSTACK, offsetof(struct pcpu, pc_aim.slbstack));
|
||||
ASSYM(PC_AIM_DBSTACK, offsetof(struct pcpu, pc_aim.dbstack));
|
||||
ASSYM(USER_SLB_SLOT, USER_SLB_SLOT);
|
||||
ASSYM(USER_SLB_SLBE, USER_SLB_SLBE);
|
||||
ASSYM(SEGMENT_MASK, SEGMENT_MASK);
|
||||
|
||||
Reference in new issue
Block a user