Add a kdb show command to print arbitrary SPRs on PowerPC

Summary:
There is often a need at the debugger to print arbitrary special
purpose registers (SPRs) on PowerPC.  Using a rewritable asm stub, print any SPR
provided on the command line.

Note, as there is no checking in this, attempting to print a nonexistent SPR
may cause a Program exception (illegal instruction, or boundedly undefined).

Note also that this relies on the kernel text pages being writable.  If in the
future this is made not the case, this will need to be reworked.

Test Plan:
Printing the Processor Version Register (PVR, SPR 287):

db> show spr 11f
SPR 287(11f): 80240012

Differential Revision: https://reviews.freebsd.org/D7403
This commit is contained in:
Justin Hibbits 2016-08-13 18:46:49 +00:00
parent fc9bbf2794
commit cbc3c68d9a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=304051
3 changed files with 43 additions and 0 deletions

View File

@ -6,3 +6,10 @@
#include <powerpc/aim/locore32.S>
#endif
/*
* XXX: This should be moved to a shared AIM/booke asm file, if one ever is
* created.
*/
ENTRY(get_spr)
mfspr %r3, 0
blr

View File

@ -848,6 +848,14 @@ ENTRY(dataloss_erratum_access)
blr
/*
* XXX: This should be moved to a shared AIM/booke asm file, if one ever is
* created.
*/
ENTRY(get_spr)
mfspr %r3, 0
blr
/************************************************************************/
/* Data section */
/************************************************************************/

View File

@ -516,3 +516,31 @@ spinlock_exit(void)
}
}
/*
* Simple ddb(4) command/hack to view any SPR on the running CPU.
* Uses a trivial asm function to perform the mfspr, and rewrites the mfspr
* instruction each time.
* XXX: Since it uses code modification, it won't work if the kernel code pages
* are marked RO.
*/
extern register_t get_spr(int);
DB_SHOW_COMMAND(spr, db_show_spr)
{
register_t spr;
volatile uint32_t *p;
int sprno, saved_sprno;
if (!have_addr)
return;
saved_sprno = sprno = (intptr_t) addr;
sprno = ((sprno & 0x3e0) >> 5) | ((sprno & 0x1f) << 5);
p = (uint32_t *)(void *)&get_spr;
*p = (*p & ~0x001ff800) | (sprno << 11);
__syncicache(get_spr, cacheline_size);
spr = get_spr(sprno);
db_printf("SPR %d(%x): %lx\n", saved_sprno, saved_sprno,
(unsigned long)spr);
}