summaryrefslogtreecommitdiffstats
path: root/sys/cddl/dev/dtrace
diff options
context:
space:
mode:
authorjhibbits <jhibbits@FreeBSD.org>2013-03-18 05:30:18 +0000
committerjhibbits <jhibbits@FreeBSD.org>2013-03-18 05:30:18 +0000
commit7b62f31cdf0ac5e5b9e97e38a21caf00e4897a45 (patch)
treeed98c02f053007502714151382d6652f85f4b682 /sys/cddl/dev/dtrace
parentc1c3be94b5168f8fb3d5164cef52767192eb6505 (diff)
downloadFreeBSD-src-7b62f31cdf0ac5e5b9e97e38a21caf00e4897a45.zip
FreeBSD-src-7b62f31cdf0ac5e5b9e97e38a21caf00e4897a45.tar.gz
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.
Diffstat (limited to 'sys/cddl/dev/dtrace')
-rw-r--r--sys/cddl/dev/dtrace/powerpc/dtrace_asm.S56
-rw-r--r--sys/cddl/dev/dtrace/powerpc/dtrace_isa.c14
-rw-r--r--sys/cddl/dev/dtrace/powerpc/dtrace_subr.c74
3 files changed, 101 insertions, 43 deletions
diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S b/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
index 8537e3c..810517f 100644
--- a/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
+++ b/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
@@ -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,22 +100,15 @@ 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
dtrace_copy(uintptr_t src, uintptr_t dest, size_t size)
@@ -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,42 +137,19 @@ 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
* for passing through the format string and arguments, and constructing a
diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c b/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
index efbca6f..a68ee65 100644
--- a/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
+++ b/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
@@ -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;
+}
diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c b/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
index 22fb442..e6f1ec0 100644
--- a/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
@@ -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;
+}
OpenPOWER on IntegriCloud