Add FBT for PowerPC DTrace. Also, clean up the DTrace assembly code,

much of which is not necessary for PowerPC.

The FBT module can likely be factored into 3 separate files: common,
intel, and powerpc, rather than duplicating most of the code between
the x86 and PowerPC flavors.

All DTrace modules for PowerPC will be MFC'd together once Fasttrap is
completed.
This commit is contained in:
Justin Hibbits 2013-03-18 05:30:18 +00:00
parent e8bedbd24a
commit 80a5635c8b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=248457
11 changed files with 1457 additions and 65 deletions

View file

@ -2313,10 +2313,10 @@ extern int dtrace_mach_aframes(void);
#if defined(__i386) || defined(__amd64)
extern int dtrace_instr_size(uchar_t *instr);
extern int dtrace_instr_size_isa(uchar_t *, model_t, int *);
extern void dtrace_invop_add(int (*)(uintptr_t, uintptr_t *, uintptr_t));
extern void dtrace_invop_remove(int (*)(uintptr_t, uintptr_t *, uintptr_t));
extern void dtrace_invop_callsite(void);
#endif
extern void dtrace_invop_add(int (*)(uintptr_t, uintptr_t *, uintptr_t));
extern void dtrace_invop_remove(int (*)(uintptr_t, uintptr_t *, uintptr_t));
#ifdef __sparc
extern int dtrace_blksuword32(uintptr_t, uint32_t *, int);
@ -2349,6 +2349,15 @@ extern void dtrace_helpers_destroy(proc_t *);
#define DTRACE_INVOP_NOP 4
#define DTRACE_INVOP_RET 5
#elif defined(__powerpc__)
#define DTRACE_INVOP_RET 1
#define DTRACE_INVOP_BCTR 2
#define DTRACE_INVOP_BLR 3
#define DTRACE_INVOP_JUMP 4
#define DTRACE_INVOP_MFLR_R0 5
#define DTRACE_INVOP_NOP 6
#endif
#ifdef __cplusplus

View file

@ -85,10 +85,10 @@ ASENTRY_NOPROF(dtrace_cas32)
1:
lwarx %r0,0,%r3
cmpw %r4,%r0
bne 2f
bne 2f
stwcx. %r5,0,%r3
bne 1b
2: mr %r3,%r0
bne 1b
2: mr %r3,%r0
blr
END(dtrace_cas32)
@ -100,21 +100,14 @@ ASENTRY_NOPROF(dtrace_casptr)
1:
lwarx %r0,0,%r3
cmpw %r4,%r0
bne 2f
bne 2f
stwcx. %r5,0,%r3
bne 1b
2: mr %r3,%r0
bne 1b
2: mr %r3,%r0
blr
END(dtrace_casptr)
/*
uintptr_t
dtrace_fulword(void *addr)
*/
ASENTRY_NOPROF(dtrace_fulword)
END(dtrace_fulword)
/*
XXX: unoptimized
void
@ -127,7 +120,7 @@ ASENTRY_NOPROF(dtrace_copy)
lbzu %r3,1(%r7)
stbu %r3,1(%r8)
addme %r5,%r5
beq 2f
beq 2f
2:
blr
END(dtrace_copy)
@ -144,41 +137,18 @@ ASENTRY_NOPROF(dtrace_copystr)
lbzu %r3,1(%r7)
stbu %r3,1(%r8)
addme %r5,%r5
beq 2f
or %r3,%r3,%r3
beq 2f
beq 2f
or %r3,%r3,%r3
beq 2f
andi. %r0,%r5,0x0fff
beq 2f
lwz %r0,0(%r6)
beq 2f
lwz %r0,0(%r6)
andi. %r0,%r0,CPU_DTRACE_BADADDR
beq 1b
beq 1b
2:
blr
END(dtrace_copystr)
/*
void dtrace_invop_init(void)
*/
ASENTRY_NOPROF(dtrace_invop_init)
/* XXX: impement it properly -- implement dtrace_invop_start */
li %r0,0
li %r3,dtrace_invop_jump_addr@l
addis %r3,%r3,dtrace_invop_jump_addr@ha
stw %r0,0(%r3)
blr
END(dtrace_invop_init)
/*
void dtrace_invop_uninit(void)
*/
ASENTRY_NOPROF(dtrace_invop_uninit)
li %r0,0
li %r3,dtrace_invop_jump_addr@l
addis %r3,%r3,dtrace_invop_jump_addr@ha
stw %r0,0(%r3)
blr
END(dtrace_invop_uninit)
/*
* The panic() and cmn_err() functions invoke vpanic() as a common entry point
* into the panic code implemented in panicsys(). vpanic() is responsible

View file

@ -567,3 +567,17 @@ dtrace_fuword64(void *uaddr)
}
return ret;
}
uintptr_t
dtrace_fulword(void *uaddr)
{
uintptr_t ret = 0;
if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) {
if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) {
DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
}
}
return ret;
}

View file

@ -49,8 +49,11 @@ __FBSDID("$FreeBSD$");
extern uintptr_t dtrace_in_probe_addr;
extern int dtrace_in_probe;
extern dtrace_id_t dtrace_probeid_error;
extern int (*dtrace_invop_jump_addr)(struct trapframe *);
int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
void dtrace_invop_init(void);
void dtrace_invop_uninit(void);
typedef struct dtrace_invop_hdlr {
int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t);
@ -72,6 +75,44 @@ dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax)
return (0);
}
void
dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
{
dtrace_invop_hdlr_t *hdlr;
hdlr = kmem_alloc(sizeof (dtrace_invop_hdlr_t), KM_SLEEP);
hdlr->dtih_func = func;
hdlr->dtih_next = dtrace_invop_hdlr;
dtrace_invop_hdlr = hdlr;
}
void
dtrace_invop_remove(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
{
dtrace_invop_hdlr_t *hdlr = dtrace_invop_hdlr, *prev = NULL;
for (;;) {
if (hdlr == NULL)
panic("attempt to remove non-existent invop handler");
if (hdlr->dtih_func == func)
break;
prev = hdlr;
hdlr = hdlr->dtih_next;
}
if (prev == NULL) {
ASSERT(dtrace_invop_hdlr == hdlr);
dtrace_invop_hdlr = hdlr->dtih_next;
} else {
ASSERT(dtrace_invop_hdlr != hdlr);
prev->dtih_next = hdlr->dtih_next;
}
kmem_free(hdlr, 0);
}
/*ARGSUSED*/
void
@ -199,3 +240,36 @@ dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which,
(uintptr_t)epid,
(uintptr_t)which, (uintptr_t)fault, (uintptr_t)fltoffs);
}
static int
dtrace_invop_start(struct trapframe *frame)
{
switch (dtrace_invop(frame->srr0, (uintptr_t *)frame, frame->fixreg[3])) {
case DTRACE_INVOP_JUMP:
break;
case DTRACE_INVOP_BCTR:
frame->srr0 = frame->ctr;
break;
case DTRACE_INVOP_BLR:
frame->srr0 = frame->lr;
break;
case DTRACE_INVOP_MFLR_R0:
frame->fixreg[0] = frame->lr ;
break;
default:
return (-1);
break;
}
return (0);
}
void dtrace_invop_init(void)
{
dtrace_invop_jump_addr = dtrace_invop_start;
}
void dtrace_invop_uninit(void)
{
dtrace_invop_jump_addr = 0;
}

File diff suppressed because it is too large Load diff

View file

@ -19,6 +19,9 @@ SUBDIR= dtmalloc \
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
SUBDIR+= fasttrap fbt systrace_linux32
.endif
.if ${MACHINE_CPUARCH} == "powerpc"
SUBDIR+= fbt
.endif
.if ${MACHINE_CPUARCH} == "amd64"
SUBDIR+= systrace_freebsd32
.endif

View file

@ -72,8 +72,10 @@ MODULE_DEPEND(dtraceall, dtnfscl, 1, 1, 1);
#if defined(NFSCLIENT)
MODULE_DEPEND(dtraceall, dtnfsclient, 1, 1, 1);
#endif
#if defined(__amd64__) || defined(__i386__)
#if defined(__amd64__) || defined(__i386__) || defined(__powerpc__)
MODULE_DEPEND(dtraceall, fbt, 1, 1, 1);
#endif
#if defined(__amd64__) || defined(__i386__)
MODULE_DEPEND(dtraceall, fasttrap, 1, 1, 1);
#endif
MODULE_DEPEND(dtraceall, lockstat, 1, 1, 1);

View file

@ -3,7 +3,11 @@
.PATH: ${.CURDIR}/../../../cddl/dev/fbt
KMOD= fbt
.if ${MACHINE_ARCH} == "powerpc"
SRCS= fbt_powerpc.c
.else
SRCS= fbt.c
.endif
SRCS+= vnode_if.h
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris \

View file

@ -130,6 +130,7 @@ systrace_probe_func_t systrace_probe_func;
dtrace_fasttrap_probe_ptr_t dtrace_fasttrap_probe_ptr;
dtrace_pid_probe_ptr_t dtrace_pid_probe_ptr;
dtrace_return_probe_ptr_t dtrace_return_probe_ptr;
int (*dtrace_invop_jump_addr)(struct trapframe *);
#endif
static struct powerpc_exception powerpc_exceptions[] = {
@ -220,10 +221,8 @@ trap(struct trapframe *frame)
/*
* XXXDTRACE: add fasttrap and pid probes handlers here (if ever)
*/
if (!user) {
if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type))
return;
}
if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type))
return;
#endif
if (user) {
@ -296,7 +295,7 @@ trap(struct trapframe *frame)
/* Identify the trap reason */
if (frame->srr1 & EXC_PGM_TRAP)
sig = SIGTRAP;
else if (ppc_instr_emulate(frame) == 0)
else if (ppc_instr_emulate(frame) == 0)
frame->srr0 += 4;
else
sig = SIGILL;
@ -311,6 +310,16 @@ trap(struct trapframe *frame)
KASSERT(cold || td->td_ucred != NULL,
("kernel trap doesn't have ucred"));
switch (type) {
#ifdef KDTRACE_HOOKS
case EXC_PGM:
if (frame->srr1 & EXC_PGM_TRAP) {
if (*(uintptr_t *)frame->srr0 == 0x7c810808) {
if (dtrace_invop_jump_addr != NULL) {
dtrace_invop_jump_addr(frame);
}
}
}
#endif
#ifdef __powerpc64__
case EXC_DSE:
if ((frame->cpu.aim.dar & SEGMENT_MASK) == USER_ADDR) {

View file

@ -242,13 +242,6 @@
#ifdef KDTRACE_HOOKS
.data
.globl dtrace_invop_jump_addr
.align 4
.type dtrace_invop_jump_addr, @object
.size dtrace_invop_jump_addr, 4
dtrace_invop_jump_addr:
.word 0
.word 0
.globl dtrace_invop_calltrap_addr
.align 4
.type dtrace_invop_calltrap_addr, @object

View file

@ -276,13 +276,6 @@ restore_kernsrs:
#ifdef KDTRACE_HOOKS
.data
.globl dtrace_invop_jump_addr
.align 8
.type dtrace_invop_jump_addr, @object
.size dtrace_invop_jump_addr, 8
dtrace_invop_jump_addr:
.word 0
.word 0
.globl dtrace_invop_calltrap_addr
.align 8
.type dtrace_invop_calltrap_addr, @object