aboutsummaryrefslogtreecommitdiff
path: root/sys/cddl/dev/dtrace/aarch64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cddl/dev/dtrace/aarch64')
-rw-r--r--sys/cddl/dev/dtrace/aarch64/dtrace_asm.S174
-rw-r--r--sys/cddl/dev/dtrace/aarch64/dtrace_isa.c409
-rw-r--r--sys/cddl/dev/dtrace/aarch64/dtrace_subr.c335
-rw-r--r--sys/cddl/dev/dtrace/aarch64/regset.h51
4 files changed, 969 insertions, 0 deletions
diff --git a/sys/cddl/dev/dtrace/aarch64/dtrace_asm.S b/sys/cddl/dev/dtrace/aarch64/dtrace_asm.S
new file mode 100644
index 000000000000..710232a0d428
--- /dev/null
+++ b/sys/cddl/dev/dtrace/aarch64/dtrace_asm.S
@@ -0,0 +1,174 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * $FreeBSD$
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#define _ASM
+#define _LOCORE
+
+#include <sys/cpuvar_defs.h>
+#include <sys/dtrace.h>
+
+#include <machine/armreg.h>
+#include <machine/asm.h>
+
+#include "assym.inc"
+
+/*
+void dtrace_membar_producer(void)
+*/
+ENTRY(dtrace_membar_producer)
+ RET
+END(dtrace_membar_producer)
+
+/*
+void dtrace_membar_consumer(void)
+*/
+ENTRY(dtrace_membar_consumer)
+ RET
+END(dtrace_membar_consumer)
+
+/*
+dtrace_icookie_t dtrace_interrupt_disable(void)
+*/
+ENTRY(dtrace_interrupt_disable)
+ mrs x0, daif
+ msr daifset, #2
+ RET
+END(dtrace_interrupt_disable)
+
+/*
+void dtrace_interrupt_enable(dtrace_icookie_t cookie)
+*/
+ENTRY(dtrace_interrupt_enable)
+ msr daif, x0
+ RET
+END(dtrace_interrupt_enable)
+/*
+uint8_t
+dtrace_fuword8_nocheck(void *addr)
+*/
+ENTRY(dtrace_fuword8_nocheck)
+ ldrb w0, [x0]
+ RET
+END(dtrace_fuword8_nocheck)
+
+/*
+uint16_t
+dtrace_fuword16_nocheck(void *addr)
+*/
+ENTRY(dtrace_fuword16_nocheck)
+ ldrh w0, [x0]
+ RET
+END(dtrace_fuword16_nocheck)
+
+/*
+uint32_t
+dtrace_fuword32_nocheck(void *addr)
+*/
+ENTRY(dtrace_fuword32_nocheck)
+ ldr w0, [x0]
+ RET
+END(dtrace_fuword32_nocheck)
+
+/*
+uint64_t
+dtrace_fuword64_nocheck(void *addr)
+*/
+ENTRY(dtrace_fuword64_nocheck)
+ ldr x0, [x0]
+ RET
+END(dtrace_fuword64_nocheck)
+
+/*
+void
+dtrace_copy(uintptr_t uaddr, uintptr_t kaddr, size_t size)
+*/
+ENTRY(dtrace_copy)
+ cbz x2, 2f /* If len == 0 then skip loop */
+1:
+ ldrb w4, [x0], #1 /* Load from uaddr */
+ strb w4, [x1], #1 /* Store in kaddr */
+ sub x2, x2, #1 /* len-- */
+ cbnz x2, 1b
+2:
+ RET
+END(dtrace_copy)
+
+/*
+void
+dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
+ volatile uint16_t *flags)
+XXX: Check for flags?
+*/
+ENTRY(dtrace_copystr)
+ cbz x2, 2f /* If len == 0 then skip loop */
+
+1: ldrb w4, [x0], #1 /* Load from uaddr */
+ strb w4, [x1], #1 /* Store in kaddr */
+ cbz w4, 2f /* If == 0 then break */
+ sub x2, x2, #1 /* len-- */
+ cbnz x2, 1b
+2:
+ RET
+END(dtrace_copystr)
+
+/*
+uintptr_t
+dtrace_caller(int aframes)
+*/
+ENTRY(dtrace_caller)
+ mov x0, #-1
+ RET
+END(dtrace_caller)
+
+/*
+uint32_t
+dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)
+*/
+ENTRY(dtrace_cas32)
+1: ldxr w3, [x0] /* Load target */
+ cmp w3, w1 /* Check if *target == cmp */
+ bne 2f /* No, return */
+ stxr w12, w2, [x0] /* Store new to target */
+ cbnz w12, 1b /* Try again if store not succeed */
+2: mov w0, w3 /* Return the value loaded from target */
+ RET
+END(dtrace_cas32)
+
+/*
+void *
+dtrace_casptr(volatile void *target, volatile void *cmp, volatile void *new)
+*/
+ENTRY(dtrace_casptr)
+1: ldxr x3, [x0] /* Load target */
+ cmp x3, x1 /* Check if *target == cmp */
+ bne 2f /* No, return */
+ stxr w12, x2, [x0] /* Store new to target */
+ cbnz w12, 1b /* Try again if store not succeed */
+2: mov x0, x3 /* Return the value loaded from target */
+ RET
+END(dtrace_casptr)
diff --git a/sys/cddl/dev/dtrace/aarch64/dtrace_isa.c b/sys/cddl/dev/dtrace/aarch64/dtrace_isa.c
new file mode 100644
index 000000000000..082bd1904279
--- /dev/null
+++ b/sys/cddl/dev/dtrace/aarch64/dtrace_isa.c
@@ -0,0 +1,409 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * $FreeBSD$
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/stack.h>
+#include <sys/pcpu.h>
+
+#include <machine/frame.h>
+#include <machine/md_var.h>
+#include <machine/reg.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+#include <machine/atomic.h>
+#include <machine/db_machdep.h>
+#include <machine/md_var.h>
+#include <machine/stack.h>
+#include <ddb/db_sym.h>
+#include <ddb/ddb.h>
+#include <sys/kdb.h>
+
+#include "regset.h"
+
+/*
+ * Wee need some reasonable default to prevent backtrace code
+ * from wandering too far
+ */
+#define MAX_FUNCTION_SIZE 0x10000
+#define MAX_PROLOGUE_SIZE 0x100
+#define MAX_USTACK_DEPTH 2048
+
+uint8_t dtrace_fuword8_nocheck(void *);
+uint16_t dtrace_fuword16_nocheck(void *);
+uint32_t dtrace_fuword32_nocheck(void *);
+uint64_t dtrace_fuword64_nocheck(void *);
+
+void
+dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
+ uint32_t *intrpc)
+{
+ struct unwind_state state;
+ int scp_offset;
+ register_t sp, fp;
+ int depth;
+
+ depth = 0;
+
+ if (intrpc != 0) {
+ pcstack[depth++] = (pc_t) intrpc;
+ }
+
+ aframes++;
+
+ __asm __volatile("mov %0, sp" : "=&r" (sp));
+
+ state.fp = (uint64_t)__builtin_frame_address(0);
+ state.sp = sp;
+ state.pc = (uint64_t)dtrace_getpcstack;
+
+ while (depth < pcstack_limit) {
+ if (!INKERNEL(state.pc) || !INKERNEL(state.fp))
+ break;
+
+ fp = state.fp;
+ state.sp = fp + 0x10;
+ /* FP to previous frame (X29) */
+ state.fp = *(register_t *)(fp);
+ /* LR (X30) */
+ state.pc = *(register_t *)(fp + 8) - 4;
+
+ /*
+ * NB: Unlike some other architectures, we don't need to
+ * explicitly insert cpu_dtrace_caller as it appears in the
+ * normal kernel stack trace rather than a special trap frame.
+ */
+ if (aframes > 0) {
+ aframes--;
+ } else {
+ pcstack[depth++] = state.pc;
+ }
+
+ }
+
+ for (; depth < pcstack_limit; depth++) {
+ pcstack[depth] = 0;
+ }
+}
+
+static int
+dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
+ uintptr_t fp)
+{
+ volatile uint16_t *flags =
+ (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
+ int ret = 0;
+ uintptr_t oldfp = fp;
+
+ ASSERT(pcstack == NULL || pcstack_limit > 0);
+
+ while (pc != 0) {
+ /*
+ * We limit the number of times we can go around this
+ * loop to account for a circular stack.
+ */
+ if (ret++ >= MAX_USTACK_DEPTH) {
+ *flags |= CPU_DTRACE_BADSTACK;
+ cpu_core[curcpu].cpuc_dtrace_illval = fp;
+ break;
+ }
+
+ if (pcstack != NULL) {
+ *pcstack++ = (uint64_t)pc;
+ pcstack_limit--;
+ if (pcstack_limit <= 0)
+ break;
+ }
+
+ if (fp == 0)
+ break;
+
+ pc = dtrace_fuword64((void *)(fp +
+ offsetof(struct arm64_frame, f_retaddr)));
+ fp = dtrace_fuword64((void *)fp);
+
+ if (fp == oldfp) {
+ *flags |= CPU_DTRACE_BADSTACK;
+ cpu_core[curcpu].cpuc_dtrace_illval = fp;
+ break;
+ }
+
+ /*
+ * ARM64TODO:
+ * This workaround might not be necessary. It needs to be
+ * revised and removed from all architectures if found
+ * unwanted. Leaving the original x86 comment for reference.
+ *
+ * This is totally bogus: if we faulted, we're going to clear
+ * the fault and break. This is to deal with the apparently
+ * broken Java stacks on x86.
+ */
+ if (*flags & CPU_DTRACE_FAULT) {
+ *flags &= ~CPU_DTRACE_FAULT;
+ break;
+ }
+
+ oldfp = fp;
+ }
+
+ return (ret);
+}
+
+void
+dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
+{
+ proc_t *p = curproc;
+ struct trapframe *tf;
+ uintptr_t pc, sp, fp;
+ volatile uint16_t *flags =
+ (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
+ int n;
+
+ if (*flags & CPU_DTRACE_FAULT)
+ return;
+
+ if (pcstack_limit <= 0)
+ return;
+
+ /*
+ * If there's no user context we still need to zero the stack.
+ */
+ if (p == NULL || (tf = curthread->td_frame) == NULL)
+ goto zero;
+
+ *pcstack++ = (uint64_t)p->p_pid;
+ pcstack_limit--;
+
+ if (pcstack_limit <= 0)
+ return;
+
+ pc = tf->tf_elr;
+ sp = tf->tf_sp;
+ fp = tf->tf_x[29];
+
+ if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
+ /*
+ * In an entry probe. The frame pointer has not yet been
+ * pushed (that happens in the function prologue). The
+ * best approach is to add the current pc as a missing top
+ * of stack and back the pc up to the caller, which is stored
+ * at the current stack pointer address since the call
+ * instruction puts it there right before the branch.
+ */
+
+ *pcstack++ = (uint64_t)pc;
+ pcstack_limit--;
+ if (pcstack_limit <= 0)
+ return;
+
+ pc = tf->tf_lr;
+ }
+
+ n = dtrace_getustack_common(pcstack, pcstack_limit, pc, fp);
+ ASSERT(n >= 0);
+ ASSERT(n <= pcstack_limit);
+
+ pcstack += n;
+ pcstack_limit -= n;
+
+zero:
+ while (pcstack_limit-- > 0)
+ *pcstack++ = 0;
+}
+
+int
+dtrace_getustackdepth(void)
+{
+
+ printf("IMPLEMENT ME: %s\n", __func__);
+
+ return (0);
+}
+
+void
+dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
+{
+
+ printf("IMPLEMENT ME: %s\n", __func__);
+}
+
+/*ARGSUSED*/
+uint64_t
+dtrace_getarg(int arg, int aframes)
+{
+
+ printf("IMPLEMENT ME: %s\n", __func__);
+
+ return (0);
+}
+
+int
+dtrace_getstackdepth(int aframes)
+{
+ struct unwind_state state;
+ int scp_offset;
+ register_t sp;
+ int depth;
+ int done;
+
+ depth = 1;
+ done = 0;
+
+ __asm __volatile("mov %0, sp" : "=&r" (sp));
+
+ state.fp = (uint64_t)__builtin_frame_address(0);
+ state.sp = sp;
+ state.pc = (uint64_t)dtrace_getstackdepth;
+
+ do {
+ done = unwind_frame(&state);
+ if (!INKERNEL(state.pc) || !INKERNEL(state.fp))
+ break;
+ depth++;
+ } while (!done);
+
+ if (depth < aframes)
+ return (0);
+ else
+ return (depth - aframes);
+}
+
+ulong_t
+dtrace_getreg(struct trapframe *rp, uint_t reg)
+{
+
+ printf("IMPLEMENT ME: %s\n", __func__);
+
+ return (0);
+}
+
+static int
+dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
+{
+
+ if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = uaddr;
+ return (0);
+ }
+
+ return (1);
+}
+
+void
+dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
+ volatile uint16_t *flags)
+{
+
+ if (dtrace_copycheck(uaddr, kaddr, size))
+ dtrace_copy(uaddr, kaddr, size);
+}
+
+void
+dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
+ volatile uint16_t *flags)
+{
+
+ if (dtrace_copycheck(uaddr, kaddr, size))
+ dtrace_copy(kaddr, uaddr, size);
+}
+
+void
+dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
+ volatile uint16_t *flags)
+{
+
+ if (dtrace_copycheck(uaddr, kaddr, size))
+ dtrace_copystr(uaddr, kaddr, size, flags);
+}
+
+void
+dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
+ volatile uint16_t *flags)
+{
+
+ if (dtrace_copycheck(uaddr, kaddr, size))
+ dtrace_copystr(kaddr, uaddr, size, flags);
+}
+
+uint8_t
+dtrace_fuword8(void *uaddr)
+{
+
+ if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ return (0);
+ }
+
+ return (dtrace_fuword8_nocheck(uaddr));
+}
+
+uint16_t
+dtrace_fuword16(void *uaddr)
+{
+
+ if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ return (0);
+ }
+
+ return (dtrace_fuword16_nocheck(uaddr));
+}
+
+uint32_t
+dtrace_fuword32(void *uaddr)
+{
+
+ if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ return (0);
+ }
+
+ return (dtrace_fuword32_nocheck(uaddr));
+}
+
+uint64_t
+dtrace_fuword64(void *uaddr)
+{
+
+ if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ return (0);
+ }
+
+ return (dtrace_fuword64_nocheck(uaddr));
+}
diff --git a/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c b/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c
new file mode 100644
index 000000000000..000de0094492
--- /dev/null
+++ b/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c
@@ -0,0 +1,335 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * $FreeBSD$
+ *
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/kmem.h>
+#include <sys/smp.h>
+#include <sys/dtrace_impl.h>
+#include <sys/dtrace_bsd.h>
+#include <machine/armreg.h>
+#include <machine/clock.h>
+#include <machine/frame.h>
+#include <machine/trap.h>
+#include <machine/vmparam.h>
+#include <vm/pmap.h>
+
+extern dtrace_id_t dtrace_probeid_error;
+extern int (*dtrace_invop_jump_addr)(struct trapframe *);
+extern void dtrace_getnanotime(struct timespec *tsp);
+
+int dtrace_invop(uintptr_t, struct trapframe *, uintptr_t);
+void dtrace_invop_init(void);
+void dtrace_invop_uninit(void);
+
+typedef struct dtrace_invop_hdlr {
+ int (*dtih_func)(uintptr_t, struct trapframe *, uintptr_t);
+ struct dtrace_invop_hdlr *dtih_next;
+} dtrace_invop_hdlr_t;
+
+dtrace_invop_hdlr_t *dtrace_invop_hdlr;
+
+int
+dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t eax)
+{
+ dtrace_invop_hdlr_t *hdlr;
+ int rval;
+
+ for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
+ if ((rval = hdlr->dtih_func(addr, frame, eax)) != 0)
+ return (rval);
+
+ return (0);
+}
+
+
+void
+dtrace_invop_add(int (*func)(uintptr_t, struct trapframe *, 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, struct trapframe *, uintptr_t))
+{
+ dtrace_invop_hdlr_t *hdlr, *prev;
+
+ 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
+dtrace_toxic_ranges(void (*func)(uintptr_t base, uintptr_t limit))
+{
+
+ (*func)(0, (uintptr_t)VM_MIN_KERNEL_ADDRESS);
+}
+
+void
+dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg)
+{
+ cpuset_t cpus;
+
+ if (cpu == DTRACE_CPUALL)
+ cpus = all_cpus;
+ else
+ CPU_SETOF(cpu, &cpus);
+
+ smp_rendezvous_cpus(cpus, smp_no_rendezvous_barrier, func,
+ smp_no_rendezvous_barrier, arg);
+}
+
+static void
+dtrace_sync_func(void)
+{
+
+}
+
+void
+dtrace_sync(void)
+{
+
+ dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL);
+}
+
+/*
+ * DTrace needs a high resolution time function which can
+ * be called from a probe context and guaranteed not to have
+ * instrumented with probes itself.
+ *
+ * Returns nanoseconds since boot.
+ */
+uint64_t
+dtrace_gethrtime()
+{
+ struct timespec curtime;
+
+ nanouptime(&curtime);
+
+ return (curtime.tv_sec * 1000000000UL + curtime.tv_nsec);
+
+}
+
+uint64_t
+dtrace_gethrestime(void)
+{
+ struct timespec current_time;
+
+ dtrace_getnanotime(&current_time);
+
+ return (current_time.tv_sec * 1000000000UL + current_time.tv_nsec);
+}
+
+/* Function to handle DTrace traps during probes. See arm64/arm64/trap.c */
+int
+dtrace_trap(struct trapframe *frame, u_int type)
+{
+ /*
+ * A trap can occur while DTrace executes a probe. Before
+ * executing the probe, DTrace blocks re-scheduling and sets
+ * a flag in its per-cpu flags to indicate that it doesn't
+ * want to fault. On returning from the probe, the no-fault
+ * flag is cleared and finally re-scheduling is enabled.
+ *
+ * Check if DTrace has enabled 'no-fault' mode:
+ *
+ */
+
+ if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
+ /*
+ * There are only a couple of trap types that are expected.
+ * All the rest will be handled in the usual way.
+ */
+ switch (type) {
+ case EXCP_DATA_ABORT:
+ /* Flag a bad address. */
+ cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR;
+ cpu_core[curcpu].cpuc_dtrace_illval = 0;
+
+ /*
+ * Offset the instruction pointer to the instruction
+ * following the one causing the fault.
+ */
+ frame->tf_elr += 4;
+ return (1);
+ default:
+ /* Handle all other traps in the usual way. */
+ break;
+ }
+ }
+
+ /* Handle the trap in the usual way. */
+ return (0);
+}
+
+void
+dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which,
+ int fault, int fltoffs, uintptr_t illval)
+{
+
+ dtrace_probe(dtrace_probeid_error, (uint64_t)(uintptr_t)state,
+ (uintptr_t)epid,
+ (uintptr_t)which, (uintptr_t)fault, (uintptr_t)fltoffs);
+}
+
+static void
+dtrace_load64(uint64_t *addr, struct trapframe *frame, u_int reg)
+{
+
+ KASSERT(reg <= 31, ("dtrace_load64: Invalid register %u", reg));
+ if (reg < nitems(frame->tf_x))
+ frame->tf_x[reg] = *addr;
+ else if (reg == 30) /* lr */
+ frame->tf_lr = *addr;
+ /* Nothing to do for load to xzr */
+}
+
+static void
+dtrace_store64(uint64_t *addr, struct trapframe *frame, u_int reg)
+{
+
+ KASSERT(reg <= 31, ("dtrace_store64: Invalid register %u", reg));
+ if (reg < nitems(frame->tf_x))
+ *addr = frame->tf_x[reg];
+ else if (reg == 30) /* lr */
+ *addr = frame->tf_lr;
+ else if (reg == 31) /* xzr */
+ *addr = 0;
+}
+
+static int
+dtrace_invop_start(struct trapframe *frame)
+{
+ int data, invop, reg, update_sp;
+ register_t arg1, arg2;
+ register_t *sp;
+ int offs;
+ int tmp;
+ int i;
+
+ invop = dtrace_invop(frame->tf_elr, frame, frame->tf_elr);
+
+ tmp = (invop & LDP_STP_MASK);
+ if (tmp == STP_64 || tmp == LDP_64) {
+ sp = (register_t *)frame->tf_sp;
+ data = invop;
+ arg1 = (data >> ARG1_SHIFT) & ARG1_MASK;
+ arg2 = (data >> ARG2_SHIFT) & ARG2_MASK;
+
+ offs = (data >> OFFSET_SHIFT) & OFFSET_MASK;
+
+ switch (tmp) {
+ case STP_64:
+ if (offs >> (OFFSET_SIZE - 1))
+ sp -= (~offs & OFFSET_MASK) + 1;
+ else
+ sp += (offs);
+ dtrace_store64(sp + 0, frame, arg1);
+ dtrace_store64(sp + 1, frame, arg2);
+ break;
+ case LDP_64:
+ dtrace_load64(sp + 0, frame, arg1);
+ dtrace_load64(sp + 1, frame, arg2);
+ if (offs >> (OFFSET_SIZE - 1))
+ sp -= (~offs & OFFSET_MASK) + 1;
+ else
+ sp += (offs);
+ break;
+ default:
+ break;
+ }
+
+ /* Update the stack pointer and program counter to continue */
+ frame->tf_sp = (register_t)sp;
+ frame->tf_elr += INSN_SIZE;
+ return (0);
+ }
+
+ if ((invop & B_MASK) == B_INSTR) {
+ data = (invop & B_DATA_MASK);
+ /* The data is the number of 4-byte words to change the pc */
+ data *= 4;
+ frame->tf_elr += data;
+ return (0);
+ }
+
+ if (invop == RET_INSTR) {
+ frame->tf_elr = frame->tf_lr;
+ return (0);
+ }
+
+ return (-1);
+}
+
+void
+dtrace_invop_init(void)
+{
+
+ dtrace_invop_jump_addr = dtrace_invop_start;
+}
+
+void
+dtrace_invop_uninit(void)
+{
+
+ dtrace_invop_jump_addr = 0;
+}
diff --git a/sys/cddl/dev/dtrace/aarch64/regset.h b/sys/cddl/dev/dtrace/aarch64/regset.h
new file mode 100644
index 000000000000..f99b48f8354f
--- /dev/null
+++ b/sys/cddl/dev/dtrace/aarch64/regset.h
@@ -0,0 +1,51 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * $FreeBSD$
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+#ifndef _REGSET_H
+#define _REGSET_H
+
+/*
+ * #pragma ident "@(#)regset.h 1.11 05/06/08 SMI"
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Place here */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _REGSET_H */