First cut of DTrace for AArch64.

Reviewed by:	andrew, emaste
Sponsored by:	ARM Limited
Differential Revision:	https://reviews.freebsd.org/D2738
This commit is contained in:
Ruslan Bukin 2015-07-01 15:51:11 +00:00
parent 8b47cda2f7
commit b78ee15e9f
24 changed files with 1349 additions and 27 deletions

View File

@ -1766,9 +1766,9 @@ cddl/lib/libctf__L: lib/libz__L
.endif
# cddl/lib/libdtrace requires lib/libproc and lib/librtld_db; it's only built
# on select architectures though (see cddl/lib/Makefile)
.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386" || \
${MACHINE_CPUARCH} == "mips" || ${MACHINE_CPUARCH} == "powerpc" || \
${MACHINE_CPUARCH} == "arm"
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_ARCH} == "amd64" || \
${MACHINE_CPUARCH} == "arm" || ${MACHINE_ARCH} == "i386" || \
${MACHINE_CPUARCH} == "mips" || ${MACHINE_CPUARCH} == "powerpc"
_prebuild_libs+= lib/libproc lib/librtld_db
.endif

View File

@ -0,0 +1,139 @@
/*
* 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
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2014 Howard Su
* Copyright 2015 George V. Neville-Neil
* Copyright 2015 Ruslan Bukin <br@bsdpad.com>
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <libgen.h>
#include <dt_impl.h>
#include <dt_pid.h>
#if !defined(sun)
#include <libproc_compat.h>
#endif
/*ARGSUSED*/
int
dt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp)
{
ftp->ftps_type = DTFTP_ENTRY;
ftp->ftps_pc = (uintptr_t)symp->st_value;
ftp->ftps_size = (size_t)symp->st_size;
ftp->ftps_noffs = 1;
ftp->ftps_offs[0] = 0;
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
strerror(errno));
return (dt_set_errno(dtp, errno));
}
return (1);
}
int
dt_pid_create_return_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, uint64_t *stret)
{
dt_dprintf("%s: unimplemented\n", __func__);
return (DT_PROC_ERR);
}
/*ARGSUSED*/
int
dt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, ulong_t off)
{
if (!ALIGNED_POINTER(off, 4))
return (DT_PROC_ALIGN);
ftp->ftps_type = DTFTP_OFFSETS;
ftp->ftps_pc = (uintptr_t)symp->st_value;
ftp->ftps_size = (size_t)symp->st_size;
ftp->ftps_noffs = 1;
ftp->ftps_offs[0] = off;
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
strerror(errno));
return (dt_set_errno(dtp, errno));
}
return (1);
}
/*ARGSUSED*/
int
dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern)
{
ulong_t i;
ftp->ftps_type = DTFTP_OFFSETS;
ftp->ftps_pc = (uintptr_t)symp->st_value;
ftp->ftps_size = (size_t)symp->st_size;
ftp->ftps_noffs = 0;
/*
* If we're matching against everything, just iterate through each
* instruction in the function, otherwise look for matching offset
* names by constructing the string and comparing it against the
* pattern.
*/
if (strcmp("*", pattern) == 0) {
for (i = 0; i < symp->st_size; i += 4) {
ftp->ftps_offs[ftp->ftps_noffs++] = i;
}
} else {
char name[sizeof (i) * 2 + 1];
for (i = 0; i < symp->st_size; i += 4) {
(void) sprintf(name, "%lx", i);
if (gmatch(name, pattern))
ftp->ftps_offs[ftp->ftps_noffs++] = i;
}
}
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
strerror(errno));
return (dt_set_errno(dtp, errno));
}
return (ftp->ftps_noffs);
}

View File

@ -227,7 +227,10 @@ prepare_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf32_t *dep)
s = &dofs[dofrh->dofr_tgtsec];
for (j = 0; j < nrel; j++) {
#if defined(__arm__)
#if defined(__aarch64__)
/* XXX */
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
#elif defined(__arm__)
/* XXX */
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
#elif defined(__i386) || defined(__amd64)
@ -426,7 +429,9 @@ prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep)
s = &dofs[dofrh->dofr_tgtsec];
for (j = 0; j < nrel; j++) {
#if defined(__arm__)
#if defined(__aarch64__)
/* XXX */
#elif defined(__arm__)
/* XXX */
#elif defined(__mips__)
/* XXX */
@ -822,7 +827,16 @@ dt_symtab_lookup(Elf_Data *data_sym, int nsym, uintptr_t addr, uint_t shn,
return (ret);
}
#if defined(__arm__)
#if defined(__aarch64__)
/* XXX */
static int
dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
uint32_t *off)
{
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
return (0);
}
#elif defined(__arm__)
/* XXX */
static int
dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,

View File

@ -26,9 +26,9 @@ _libzpool= libzpool
.endif
.endif
.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386" || \
${MACHINE_CPUARCH} == "mips" || ${MACHINE_CPUARCH} == "powerpc" || \
${MACHINE_CPUARCH} == "arm"
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_ARCH} == "amd64" || \
${MACHINE_CPUARCH} == "arm" || ${MACHINE_ARCH} == "i386" || \
${MACHINE_CPUARCH} == "mips" || ${MACHINE_CPUARCH} == "powerpc"
_drti= drti
_libdtrace= libdtrace
.endif

View File

@ -69,27 +69,31 @@ CFLAGS+= -I${.OBJDIR} -I${.CURDIR} \
#CFLAGS+= -DYYDEBUG
.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
.if ${MACHINE_CPUARCH} == "aarch64"
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/aarch64
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/aarch64
.PATH: ${.CURDIR}/../../../sys/cddl/dev/dtrace/aarch64
.elif ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/dev/dtrace/x86
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/intel -DDIS_MEM
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/i386
.PATH: ${.CURDIR}/../../../sys/cddl/dev/dtrace/${MACHINE_ARCH}
.PATH: ${.CURDIR}/../../../sys/cddl/dev/dtrace/x86
.elif ${MACHINE_CPUARCH} == "sparc64"
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/sparc
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/sparc
.elif ${MACHINE_CPUARCH} == "mips"
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/mips
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/mips
.PATH: ${.CURDIR}/../../../sys/cddl/dev/dtrace/mips
.elif ${MACHINE_CPUARCH} == "arm"
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/arm
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/arm
.PATH: ${.CURDIR}/../../../sys/cddl/dev/dtrace/arm
.elif ${MACHINE_CPUARCH} == "mips"
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/mips
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/mips
.PATH: ${.CURDIR}/../../../sys/cddl/dev/dtrace/mips
.elif ${MACHINE_CPUARCH} == "powerpc"
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/powerpc
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/powerpc
.PATH: ${.CURDIR}/../../../sys/cddl/dev/dtrace/powerpc
.elif ${MACHINE_CPUARCH} == "sparc64"
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/sparc
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/sparc
.else
# temporary hack
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/intel

View File

@ -30,7 +30,7 @@ _plockstat= plockstat
.endif
.endif
.if ${MACHINE_CPUARCH} == "arm"
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm"
_dtrace= dtrace
_dtruss= dtruss
_lockstat= lockstat

View File

@ -215,8 +215,9 @@ _libldns= libldns
# sense to build when clang is enabled at all. Furthermore, they can only be
# built for certain architectures.
.if ${MK_CLANG} != "no" && ${COMPILER_TYPE} == "clang" && \
(${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" || \
(${MACHINE_CPUARCH} == "arm" && ${MACHINE_ARCH} != "armeb"))
(${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \
(${MACHINE_CPUARCH} == "arm" && ${MACHINE_ARCH} != "armeb") || \
(${MACHINE_CPUARCH} == "i386"))
_libclang_rt= libclang_rt
.endif
@ -273,7 +274,7 @@ _libsmb= libsmb
_libsmb= libsmb
.endif
.if ${MACHINE_CPUARCH} == "arm"
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm"
_libsmb= libsmb
_libproc= libproc
_librtld_db= librtld_db

View File

@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
.macro save_registers el
.if \el == 1
mov x18, sp
sub sp, sp, #128
.endif
stp x28, x29, [sp, #-16]!
stp x26, x27, [sp, #-16]!

View File

@ -53,6 +53,10 @@ __FBSDID("$FreeBSD$");
#include <machine/pcpu.h>
#include <machine/vmparam.h>
#ifdef KDTRACE_HOOKS
#include <sys/dtrace_bsd.h>
#endif
#ifdef VFP
#include <machine/vfp.h>
#endif
@ -72,6 +76,8 @@ void do_el1h_sync(struct trapframe *);
void do_el0_sync(struct trapframe *);
void do_el0_error(struct trapframe *);
int (*dtrace_invop_jump_addr)(struct trapframe *);
static __inline void
call_trapsignal(struct thread *td, int sig, u_long code)
{
@ -230,6 +236,11 @@ do_el1h_sync(struct trapframe *frame)
esr = READ_SPECIALREG(esr_el1);
exception = ESR_ELx_EXCEPTION(esr);
#ifdef KDTRACE_HOOKS
if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, exception))
return;
#endif
/*
* Sanity check we are in an exception er can handle. The IL bit
* is used to indicate the instruction length, except in a few
@ -252,6 +263,13 @@ do_el1h_sync(struct trapframe *frame)
data_abort(frame, esr, 0);
break;
case EXCP_BRK:
#ifdef KDTRACE_HOOKS
if ((esr & ESR_ELx_ISS_MASK) == 0x40d && \
dtrace_invop_jump_addr != 0) {
dtrace_invop_jump_addr(frame);
break;
}
#endif
case EXCP_WATCHPT_EL1:
case EXCP_SOFTSTP_EL1:
#ifdef KDB

View File

@ -0,0 +1,29 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* XXX: Placeholder for AArch64 fasttrap code
*/

View File

@ -0,0 +1,46 @@
/*
* 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
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _FASTTRAP_ISA_H
#define _FASTTRAP_ISA_H
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef uint32_t fasttrap_instr_t;
/* XXX: Place for AArch64 fasttrap headers */
#ifdef __cplusplus
}
#endif
#endif /* _FASTTRAP_ISA_H */

View File

@ -11884,7 +11884,8 @@ dtrace_buffer_alloc(dtrace_buffer_t *bufs, size_t size, int flags,
int i;
*factor = 1;
#if defined(__amd64__) || defined(__arm__) || defined(__mips__) || defined(__powerpc__)
#if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) || \
defined(__mips__) || defined(__powerpc__)
/*
* FreeBSD isn't good at limiting the amount of memory we
* ask to malloc, so let's place a limit here before trying

View File

@ -2445,6 +2445,34 @@ extern void dtrace_helpers_destroy(proc_t *);
#define DTRACE_INVOP_POPM 2
#define DTRACE_INVOP_B 3
#elif defined(__aarch64__)
#define INSN_SIZE 4
#define B_MASK 0xff000000
#define B_DATA_MASK 0x00ffffff
#define B_INSTR 0x14000000
#define RET_INSTR 0xd65f03c0
#define LDP_STP_MASK 0xffc00000
#define STP_32 0x29800000
#define STP_64 0xa9800000
#define LDP_32 0x28c00000
#define LDP_64 0xa8c00000
#define LDP_STP_PREIND (1 << 24)
#define LDP_STP_DIR (1 << 22) /* Load instruction */
#define ARG1_SHIFT 0
#define ARG1_MASK 0x1f
#define ARG2_SHIFT 10
#define ARG2_MASK 0x1f
#define OFFSET_SHIFT 15
#define OFFSET_SIZE 7
#define OFFSET_MASK ((1 << OFFSET_SIZE) - 1)
#define DTRACE_INVOP_PUSHM 1
#define DTRACE_INVOP_RET 2
#define DTRACE_INVOP_B 3
#endif

View File

@ -0,0 +1,173 @@
/*
* 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.s"
/*
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)
msr daifset, #2
RET
END(dtrace_interrupt_disable)
/*
void dtrace_interrupt_enable(dtrace_icookie_t cookie)
*/
ENTRY(dtrace_interrupt_enable)
msr daifclr, #2
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)

View File

@ -0,0 +1,287 @@
/*
* 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/vmparam.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
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;
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 (unwind_frame(&state))
break;
if (!INKERNEL(state.pc) || !INKERNEL(state.fp))
break;
/*
* 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;
}
}
void
dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
{
printf("IMPLEMENT ME: %s\n", __func__);
}
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));
}

View File

@ -0,0 +1,311 @@
/*
* 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 <vm/pmap.h>
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 *);
extern void dtrace_getnanotime(struct timespec *tsp);
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);
struct dtrace_invop_hdlr *dtih_next;
} dtrace_invop_hdlr_t;
dtrace_invop_hdlr_t *dtrace_invop_hdlr;
int
dtrace_invop(uintptr_t addr, uintptr_t *stack, 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, stack, eax)) != 0)
return (rval);
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, *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))
{
printf("IMPLEMENT ME: dtrace_toxic_ranges\n");
}
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_rendevous_barrier, func,
smp_no_rendevous_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 it's 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 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, (uintptr_t *)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);
*(sp + 0) = frame->tf_x[arg1];
*(sp + 1) = frame->tf_x[arg2];
break;
case LDP_64:
frame->tf_x[arg1] = *(sp + 0);
frame->tf_x[arg2] = *(sp + 1);
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;
}

View File

@ -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 */

View File

@ -0,0 +1,180 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
*
* Portions Copyright 2006-2008 John Birrell jb@freebsd.org
* Portions Copyright 2013 Justin Hibbits jhibbits@freebsd.org
* Portions Copyright 2013 Howard Su howardsu@freebsd.org
* Portions Copyright 2015 Ruslan Bukin <br@bsdpad.com>
*
* $FreeBSD$
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/dtrace.h>
#include "fbt.h"
#define AARCH64_BRK 0xd4200000
#define AARCH64_BRK_IMM16_SHIFT 5
#define AARCH64_BRK_IMM16_VAL (0x40d << AARCH64_BRK_IMM16_SHIFT)
#define FBT_PATCHVAL (AARCH64_BRK | AARCH64_BRK_IMM16_VAL)
#define FBT_ENTRY "entry"
#define FBT_RETURN "return"
int
fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
{
struct trapframe *frame;
solaris_cpu_t *cpu;
fbt_probe_t *fbt;
frame = (struct trapframe *)stack;
cpu = &solaris_cpu[curcpu];
fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
fbt->fbtp_invop_cnt++;
cpu->cpu_dtrace_caller = addr;
dtrace_probe(fbt->fbtp_id, frame->tf_x[0],
frame->tf_x[1], frame->tf_x[2],
frame->tf_x[3], frame->tf_x[4]);
cpu->cpu_dtrace_caller = 0;
return (fbt->fbtp_savedval);
}
}
return (0);
}
void
fbt_patch_tracepoint(fbt_probe_t *fbt, fbt_patchval_t val)
{
*fbt->fbtp_patchpoint = val;
cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4);
}
int
fbt_provide_module_function(linker_file_t lf, int symindx,
linker_symval_t *symval, void *opaque)
{
fbt_probe_t *fbt, *retfbt;
uint32_t *target, *start;
uint32_t *instr, *limit;
const char *name;
char *modname;
int offs;
modname = opaque;
name = symval->name;
/* Check if function is excluded from instrumentation */
if (fbt_excluded(name))
return (0);
instr = (uint32_t *)(symval->value);
limit = (uint32_t *)(symval->value + symval->size);
/* Look for stp (pre-indexed) operation */
for (; instr < limit; instr++) {
if ((*instr & LDP_STP_MASK) == STP_64)
break;
}
if (instr >= limit)
return (0);
fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
fbt->fbtp_name = name;
fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
name, FBT_ENTRY, 3, fbt);
fbt->fbtp_patchpoint = instr;
fbt->fbtp_ctl = lf;
fbt->fbtp_loadcnt = lf->loadcnt;
fbt->fbtp_savedval = *instr;
fbt->fbtp_patchval = FBT_PATCHVAL;
fbt->fbtp_rval = DTRACE_INVOP_PUSHM;
fbt->fbtp_symindx = symindx;
fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
lf->fbt_nentries++;
retfbt = NULL;
again:
for (; instr < limit; instr++) {
if (*instr == RET_INSTR)
break;
else if ((*instr & B_MASK) == B_INSTR) {
offs = (*instr & B_DATA_MASK);
offs *= 4;
target = (instr + offs);
start = (uint32_t *)symval->value;
if (target >= limit || target < start)
break;
}
}
if (instr >= limit)
return (0);
/*
* We have a winner!
*/
fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
fbt->fbtp_name = name;
if (retfbt == NULL) {
fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
name, FBT_RETURN, 3, fbt);
} else {
retfbt->fbtp_next = fbt;
fbt->fbtp_id = retfbt->fbtp_id;
}
retfbt = fbt;
fbt->fbtp_patchpoint = instr;
fbt->fbtp_ctl = lf;
fbt->fbtp_loadcnt = lf->loadcnt;
fbt->fbtp_symindx = symindx;
if ((*instr & B_MASK) == B_INSTR)
fbt->fbtp_rval = DTRACE_INVOP_B;
else
fbt->fbtp_rval = DTRACE_INVOP_RET;
fbt->fbtp_savedval = *instr;
fbt->fbtp_patchval = FBT_PATCHVAL;
fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
lf->fbt_nentries++;
instr++;
goto again;
}

View File

@ -0,0 +1,30 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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$
*
*/
#ifndef _FBT_ISA_H_
#define _FBT_ISA_H_
typedef uint32_t fbt_patchval_t;
#endif

View File

@ -43,9 +43,8 @@
#include <sys/dtrace.h>
#include <sys/lockstat.h>
#if defined(__i386__) || defined(__amd64__) || \
defined(__mips__) || defined(__powerpc__) || \
defined(__arm__)
#if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) || \
defined(__i386__) || defined(__mips__) || defined(__powerpc__)
#define LOCKSTAT_AFRAMES 1
#else
#error "architecture not supported"

View File

@ -140,6 +140,11 @@ struct profile_probe_percpu;
#define PROF_ARTIFICIAL_FRAMES 10
#endif
#ifdef __aarch64__
/* TODO: verify */
#define PROF_ARTIFICIAL_FRAMES 10
#endif
typedef struct profile_probe {
char prof_name[PROF_NAMELEN];
dtrace_id_t prof_id;

View File

@ -66,3 +66,7 @@ libkern/flsl.c standard
libkern/flsll.c standard
libkern/memmove.c standard
libkern/memset.c standard
cddl/compat/opensolaris/kern/opensolaris_atomic.c optional zfs | dtrace compile-with "${CDDL_C}"
cddl/dev/dtrace/aarch64/dtrace_asm.S optional dtrace compile-with "${DTRACE_S}"
cddl/dev/dtrace/aarch64/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}"
cddl/dev/fbt/aarch64/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}"

View File

@ -22,7 +22,7 @@ SUBDIR+= fbt fasttrap
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_ARCH} == "powerpc64"
SUBDIR+= systrace_freebsd32
.endif
.if ${MACHINE_CPUARCH} == "arm"
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm"
SUBDIR+= fbt
.endif
.include <bsd.subdir.mk>

View File

@ -69,7 +69,8 @@ MODULE_DEPEND(dtraceall, dtmalloc, 1, 1, 1);
#if defined(NFSCL)
MODULE_DEPEND(dtraceall, dtnfscl, 1, 1, 1);
#endif
#if defined(__amd64__) || defined(__i386__) || defined(__powerpc__) || defined(__arm__)
#if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) || \
defined(__i386__) || defined(__powerpc__)
MODULE_DEPEND(dtraceall, fbt, 1, 1, 1);
#endif
#if defined(__amd64__) || defined(__i386__)