View | Details | Raw Unified | Return to bug 192516 | Differences between
and this patch

Collapse All | Expand All

(-)b/cddl/contrib/opensolaris/lib/libdtrace/arm/dt_isadep.c (+181 lines)
Added Link Here
1
/*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License, Version 1.0 only
6
 * (the "License").  You may not use this file except in compliance
7
 * with the License.
8
 *
9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
 * or http://www.opensolaris.org/os/licensing.
11
 * See the License for the specific language governing permissions
12
 * and limitations under the License.
13
 *
14
 * When distributing Covered Code, include this CDDL HEADER in each
15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
 * If applicable, add the following below this CDDL HEADER, with the
17
 * fields enclosed by brackets "[]" replaced with your own identifying
18
 * information: Portions Copyright [yyyy] [name of copyright owner]
19
 *
20
 * CDDL HEADER END
21
 */
22
/*
23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24
 * Use is subject to license terms.
25
 */
26
27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29
#include <stdlib.h>
30
#include <assert.h>
31
#include <errno.h>
32
#include <string.h>
33
#include <libgen.h>
34
35
#include <dt_impl.h>
36
#include <dt_pid.h>
37
38
#define	OP(x)		((x) >> 30)
39
#define	OP2(x)		(((x) >> 22) & 0x07)
40
#define	COND(x)		(((x) >> 25) & 0x0f)
41
#define	A(x)		(((x) >> 29) & 0x01)
42
43
#define	OP_BRANCH	0
44
45
#define	OP2_BPcc	0x1
46
#define	OP2_Bicc	0x2
47
#define	OP2_BPr		0x3
48
#define	OP2_FBPfcc	0x5
49
#define	OP2_FBfcc	0x6
50
51
/*ARGSUSED*/
52
int
53
dt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
54
    fasttrap_probe_spec_t *ftp, const GElf_Sym *symp)
55
{
56
	ftp->ftps_type = DTFTP_ENTRY;
57
	ftp->ftps_pc = (uintptr_t)symp->st_value;
58
	ftp->ftps_size = (size_t)symp->st_size;
59
	ftp->ftps_noffs = 1;
60
	ftp->ftps_offs[0] = 0;
61
62
	if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
63
		dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
64
		    strerror(errno));
65
		return (dt_set_errno(dtp, errno));
66
	}
67
68
	return (1);
69
}
70
71
int
72
dt_pid_create_return_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
73
    fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, uint64_t *stret)
74
{
75
76
	uint32_t *text;
77
	int i;
78
	int srdepth = 0;
79
80
	dt_dprintf("%s: unimplemented\n", __func__);
81
	return (DT_PROC_ERR);
82
83
	if ((text = malloc(symp->st_size + 4)) == NULL) {
84
		dt_dprintf("mr sparkle: malloc() failed\n");
85
		return (DT_PROC_ERR);
86
	}
87
88
	if (Pread(P, text, symp->st_size, symp->st_value) != symp->st_size) {
89
		dt_dprintf("mr sparkle: Pread() failed\n");
90
		free(text);
91
		return (DT_PROC_ERR);
92
	}
93
94
	/*
95
	 * Leave a dummy instruction in the last slot to simplify edge
96
	 * conditions.
97
	 */
98
	text[symp->st_size / 4] = 0;
99
100
	ftp->ftps_type = DTFTP_RETURN;
101
	ftp->ftps_pc = symp->st_value;
102
	ftp->ftps_size = symp->st_size;
103
	ftp->ftps_noffs = 0;
104
105
106
	free(text);
107
	if (ftp->ftps_noffs > 0) {
108
		if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
109
			dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
110
			    strerror(errno));
111
			return (dt_set_errno(dtp, errno));
112
		}
113
	}
114
115
116
	return (ftp->ftps_noffs);
117
}
118
119
/*ARGSUSED*/
120
int
121
dt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
122
    fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, ulong_t off)
123
{
124
	if (off & 0x3)
125
		return (DT_PROC_ALIGN);
126
127
	ftp->ftps_type = DTFTP_OFFSETS;
128
	ftp->ftps_pc = (uintptr_t)symp->st_value;
129
	ftp->ftps_size = (size_t)symp->st_size;
130
	ftp->ftps_noffs = 1;
131
	ftp->ftps_offs[0] = off;
132
133
	if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
134
		dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
135
		    strerror(errno));
136
		return (dt_set_errno(dtp, errno));
137
	}
138
139
	return (1);
140
}
141
142
/*ARGSUSED*/
143
int
144
dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
145
    fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern)
146
{
147
	ulong_t i;
148
149
	ftp->ftps_type = DTFTP_OFFSETS;
150
	ftp->ftps_pc = (uintptr_t)symp->st_value;
151
	ftp->ftps_size = (size_t)symp->st_size;
152
	ftp->ftps_noffs = 0;
153
154
	/*
155
	 * If we're matching against everything, just iterate through each
156
	 * instruction in the function, otherwise look for matching offset
157
	 * names by constructing the string and comparing it against the
158
	 * pattern.
159
	 */
160
	if (strcmp("*", pattern) == 0) {
161
		for (i = 0; i < symp->st_size; i += 4) {
162
			ftp->ftps_offs[ftp->ftps_noffs++] = i;
163
		}
164
	} else {
165
		char name[sizeof (i) * 2 + 1];
166
167
		for (i = 0; i < symp->st_size; i += 4) {
168
			(void) sprintf(name, "%lx", i);
169
			if (gmatch(name, pattern))
170
				ftp->ftps_offs[ftp->ftps_noffs++] = i;
171
		}
172
	}
173
174
	if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
175
		dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
176
		    strerror(errno));
177
		return (dt_set_errno(dtp, errno));
178
	}
179
180
	return (ftp->ftps_noffs);
181
}
(-)b/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c (-2 / +2 lines)
Lines 169-180 write_objects(iidesc_t *idp, ctf_buf_t *b) Link Here
169
{
169
{
170
	ushort_t id = (idp ? idp->ii_dtype->t_id : 0);
170
	ushort_t id = (idp ? idp->ii_dtype->t_id : 0);
171
171
172
	ctf_buf_write(b, &id, sizeof (id));
173
174
	if (target_requires_swap) {
172
	if (target_requires_swap) {
175
		SWAP_16(id);
173
		SWAP_16(id);
176
	}
174
	}
177
175
176
	ctf_buf_write(b, &id, sizeof (id));
177
178
	debug(3, "Wrote object %s (%d)\n", (idp ? idp->ii_name : "(null)"), id);
178
	debug(3, "Wrote object %s (%d)\n", (idp ? idp->ii_name : "(null)"), id);
179
}
179
}
180
180
(-)b/cddl/lib/Makefile (-1 / +2 lines)
Lines 22-28 _libzpool= libzpool Link Here
22
.endif
22
.endif
23
23
24
.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386" || \
24
.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386" || \
25
	${MACHINE_CPUARCH} == "mips" || ${MACHINE_CPUARCH} == "powerpc"
25
	${MACHINE_CPUARCH} == "mips" || ${MACHINE_CPUARCH} == "powerpc" || \
26
	${MACHINE_CPUARCH} == "arm"
26
_drti=		drti
27
_drti=		drti
27
_libdtrace=	libdtrace
28
_libdtrace=	libdtrace
28
.endif
29
.endif
(-)b/cddl/lib/libdtrace/Makefile (+4 lines)
Lines 79-84 CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/sparc Link Here
79
CFLAGS+=	-I${OPENSOLARIS_SYS_DISTDIR}/uts/mips
79
CFLAGS+=	-I${OPENSOLARIS_SYS_DISTDIR}/uts/mips
80
.PATH:		${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/mips
80
.PATH:		${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/mips
81
.PATH:		${.CURDIR}/../../../sys/cddl/dev/dtrace/mips
81
.PATH:		${.CURDIR}/../../../sys/cddl/dev/dtrace/mips
82
.elif ${MACHINE_CPUARCH} == "arm"
83
CFLAGS+=	-I${OPENSOLARIS_SYS_DISTDIR}/uts/arm
84
.PATH:		${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/arm
85
.PATH:		${.CURDIR}/../../../sys/cddl/dev/dtrace/arm
82
.elif ${MACHINE_CPUARCH} == "powerpc"
86
.elif ${MACHINE_CPUARCH} == "powerpc"
83
CFLAGS+=	-I${OPENSOLARIS_SYS_DISTDIR}/uts/powerpc
87
CFLAGS+=	-I${OPENSOLARIS_SYS_DISTDIR}/uts/powerpc
84
.PATH:		${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/powerpc
88
.PATH:		${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/powerpc
(-)b/cddl/usr.sbin/Makefile (+6 lines)
Lines 21-26 _dtruss= dtruss Link Here
21
_lockstat=	lockstat
21
_lockstat=	lockstat
22
.endif
22
.endif
23
23
24
.if ${MACHINE_CPUARCH} == "arm"
25
_dtrace=	dtrace
26
_lockstat=	lockstat
27
_dtruss=	dtruss
28
.endif
29
24
.if ${MACHINE_CPUARCH} == "mips"
30
.if ${MACHINE_CPUARCH} == "mips"
25
_dtrace=	dtrace
31
_dtrace=	dtrace
26
.endif
32
.endif
(-)b/lib/Makefile (+6 lines)
Lines 233-238 _libsmb= libsmb Link Here
233
_libsmb=	libsmb
233
_libsmb=	libsmb
234
.endif
234
.endif
235
235
236
.if ${MACHINE_CPUARCH} == "arm"
237
_libsmb=	libsmb
238
_libproc=	libproc
239
_librtld_db=	librtld_db
240
.endif
241
236
.if ${MK_OPENSSL} != "no"
242
.if ${MK_OPENSSL} != "no"
237
_libmp=		libmp
243
_libmp=		libmp
238
.endif
244
.endif
(-)b/lib/libproc/proc_bkpt.c (+3 lines)
Lines 51-56 __FBSDID("$FreeBSD$"); Link Here
51
#elif defined(__powerpc__)
51
#elif defined(__powerpc__)
52
#define BREAKPOINT_INSTR	0x7fe00008	/* trap */
52
#define BREAKPOINT_INSTR	0x7fe00008	/* trap */
53
#define BREAKPOINT_INSTR_SZ 4
53
#define BREAKPOINT_INSTR_SZ 4
54
#elif defined(__arm__)
55
#define BREAKPOINT_INSTR	0xe7ffffff	/* bkpt */
56
#define BREAKPOINT_INSTR_SZ	4
54
#else
57
#else
55
#error "Add support for your architecture"
58
#error "Add support for your architecture"
56
#endif
59
#endif
(-)b/lib/libproc/proc_regs.c (+8 lines)
Lines 56-61 proc_regget(struct proc_handle *phdl, proc_reg_t reg, unsigned long *regvalue) Link Here
56
	case REG_PC:
56
	case REG_PC:
57
#if defined(__amd64__)
57
#if defined(__amd64__)
58
		*regvalue = regs.r_rip;
58
		*regvalue = regs.r_rip;
59
#elif defined(__arm__)
60
		*regvalue = regs.r_pc;
59
#elif defined(__i386__)
61
#elif defined(__i386__)
60
		*regvalue = regs.r_eip;
62
		*regvalue = regs.r_eip;
61
#elif defined(__mips__)
63
#elif defined(__mips__)
Lines 67-72 proc_regget(struct proc_handle *phdl, proc_reg_t reg, unsigned long *regvalue) Link Here
67
	case REG_SP:
69
	case REG_SP:
68
#if defined(__amd64__)
70
#if defined(__amd64__)
69
		*regvalue = regs.r_rsp;
71
		*regvalue = regs.r_rsp;
72
#elif defined(__arm__)
73
		*regvalue = regs.r_sp;
70
#elif defined(__i386__)
74
#elif defined(__i386__)
71
		*regvalue = regs.r_esp;
75
		*regvalue = regs.r_esp;
72
#elif defined(__mips__)
76
#elif defined(__mips__)
Lines 99-104 proc_regset(struct proc_handle *phdl, proc_reg_t reg, unsigned long regvalue) Link Here
99
	case REG_PC:
103
	case REG_PC:
100
#if defined(__amd64__)
104
#if defined(__amd64__)
101
		regs.r_rip = regvalue;
105
		regs.r_rip = regvalue;
106
#elif defined(__arm__)
107
		regs.r_pc = regvalue;
102
#elif defined(__i386__)
108
#elif defined(__i386__)
103
		regs.r_eip = regvalue;
109
		regs.r_eip = regvalue;
104
#elif defined(__mips__)
110
#elif defined(__mips__)
Lines 110-115 proc_regset(struct proc_handle *phdl, proc_reg_t reg, unsigned long regvalue) Link Here
110
	case REG_SP:
116
	case REG_SP:
111
#if defined(__amd64__)
117
#if defined(__amd64__)
112
		regs.r_rsp = regvalue;
118
		regs.r_rsp = regvalue;
119
#elif defined(__arm__)
120
		regs.r_sp = regvalue;
113
#elif defined(__i386__)
121
#elif defined(__i386__)
114
		regs.r_esp = regvalue;
122
		regs.r_esp = regvalue;
115
#elif defined(__mips__)
123
#elif defined(__mips__)
(-)b/sys/arm/arm/exception.S (-1 / +28 lines)
Lines 47-58 Link Here
47
 */
47
 */
48
48
49
#include "assym.s"
49
#include "assym.s"
50
50
#include "opt_kdtrace.h"
51
#include <machine/asm.h>
51
#include <machine/asm.h>
52
#include <machine/armreg.h>
52
#include <machine/armreg.h>
53
#include <machine/asmacros.h>
53
#include <machine/asmacros.h>
54
__FBSDID("$FreeBSD$");
54
__FBSDID("$FreeBSD$");
55
55
56
#ifdef KDTRACE_HOOKS
57
	.bss
58
	.align 4
59
	.global	_C_LABEL(dtrace_invop_jump_addr)
60
_C_LABEL(dtrace_invop_jump_addr):
61
	.word 0
62
	.word 0
63
64
	.global	_C_LABEL(dtrace_invop_calltrap_addr)
65
_C_LABEL(dtrace_invop_calltrap_addr):
66
	.word 0
67
	.word 0
68
#endif
69
56
	.text	
70
	.text	
57
	.align	0
71
	.align	0
58
72
Lines 239-245 END(undefined_entry) Link Here
239
253
240
ENTRY_NP(undefinedinstruction_bounce)
254
ENTRY_NP(undefinedinstruction_bounce)
241
	PUSHFRAMEINSVC
255
	PUSHFRAMEINSVC
256
#ifdef notyet
257
	adr	r1, dtrace_invop_jump_addr	
258
	ldr	r0, r1
259
	cmp	r0, #0
260
	beq	normal
261
	
262
	mrs	r2, spsr_all
263
	tst 	r2, #PSR_MODE
264
	bne     normal
242
265
266
	bl      r0
267
	
268
normal:		
269
#endif
243
	mov	r0, sp
270
	mov	r0, sp
244
	adr	lr, exception_exit
271
	adr	lr, exception_exit
245
	b	_C_LABEL(undefinedinstruction)
272
	b	_C_LABEL(undefinedinstruction)
(-)b/sys/arm/arm/identcpu.c (-1 / +1 lines)
Lines 461-467 identify_arm_cpu(void) Link Here
461
	u_int8_t type, linesize;
461
	u_int8_t type, linesize;
462
	int i;
462
	int i;
463
463
464
	cpuid = cpu_id();
464
	cpuid = cpu_ident();
465
465
466
	if (cpuid == 0) {
466
	if (cpuid == 0) {
467
		printf("Processor failed probe - no CPU ID\n");
467
		printf("Processor failed probe - no CPU ID\n");
(-)b/sys/arm/arm/machdep.c (-2 / +2 lines)
Lines 835-842 fake_preload_metadata(struct arm_boot_params *abp __unused) Link Here
835
	strcpy((char*)&fake_preload[i++], "kernel");
835
	strcpy((char*)&fake_preload[i++], "kernel");
836
	i += 1;
836
	i += 1;
837
	fake_preload[i++] = MODINFO_TYPE;
837
	fake_preload[i++] = MODINFO_TYPE;
838
	fake_preload[i++] = strlen("elf kernel") + 1;
838
	fake_preload[i++] = strlen("/boot/kernel/kernel") + 1;
839
	strcpy((char*)&fake_preload[i++], "elf kernel");
839
	strcpy((char*)&fake_preload[i++], "/boot/kernel/kernel");
840
	i += 2;
840
	i += 2;
841
	fake_preload[i++] = MODINFO_ADDR;
841
	fake_preload[i++] = MODINFO_ADDR;
842
	fake_preload[i++] = sizeof(vm_offset_t);
842
	fake_preload[i++] = sizeof(vm_offset_t);
(-)b/sys/arm/arm/trap.c (+35 lines)
Lines 80-85 Link Here
80
80
81
81
82
#include "opt_ktrace.h"
82
#include "opt_ktrace.h"
83
#include "opt_kdtrace.h"
83
84
84
#include <sys/cdefs.h>
85
#include <sys/cdefs.h>
85
__FBSDID("$FreeBSD$");
86
__FBSDID("$FreeBSD$");
Lines 122-127 __FBSDID("$FreeBSD$"); Link Here
122
#include <sys/kdb.h>
123
#include <sys/kdb.h>
123
#endif
124
#endif
124
125
126
#ifdef KDTRACE_HOOKS
127
#include <sys/dtrace_bsd.h>
128
 
129
/*
130
 * This is a hook which is initialised by the dtrace module
131
 * to handle traps which might occur during DTrace probe
132
 * execution.
133
 */
134
dtrace_trap_func_t	dtrace_trap_func;
135
136
dtrace_doubletrap_func_t	dtrace_doubletrap_func;
137
138
/*
139
 * This is a hook which is initialised by the systrace module
140
 * when it is loaded. This keeps the DTrace syscall provider
141
 * implementation opaque. 
142
 */
143
systrace_probe_func_t	systrace_probe_func;
144
145
/*
146
 * These hooks are necessary for the pid and usdt providers.
147
 */
148
dtrace_pid_probe_ptr_t		dtrace_pid_probe_ptr;
149
dtrace_return_probe_ptr_t	dtrace_return_probe_ptr;
150
#endif
125
151
126
void swi_handler(struct trapframe *);
152
void swi_handler(struct trapframe *);
127
void undefinedinstruction(struct trapframe *);
153
void undefinedinstruction(struct trapframe *);
Lines 452-457 data_abort_handler(struct trapframe *tf) Link Here
452
		printf("\nvm_fault(%p, %x, %x, 0) -> %x\n", map, va, ftype,
478
		printf("\nvm_fault(%p, %x, %x, 0) -> %x\n", map, va, ftype,
453
		    error);
479
		    error);
454
		dab_fatal(tf, fsr, far, td, &ksig);
480
		dab_fatal(tf, fsr, far, td, &ksig);
481
		return;
455
	}
482
	}
456
483
457
484
Lines 492-497 dab_fatal(struct trapframe *tf, u_int fsr, u_int far, struct thread *td, Link Here
492
{
519
{
493
	const char *mode;
520
	const char *mode;
494
521
522
#ifdef KDTRACE_HOOKS
523
	if (!TRAP_USERMODE(tf))
524
	{
525
		if (dtrace_trap_func != NULL && (*dtrace_trap_func)(tf, far & FAULT_TYPE_MASK))
526
			return (0);
527
	}
528
#endif
529
495
	mode = TRAP_USERMODE(tf) ? "user" : "kernel";
530
	mode = TRAP_USERMODE(tf) ? "user" : "kernel";
496
531
497
	disable_interrupts(I32_bit|F32_bit);
532
	disable_interrupts(I32_bit|F32_bit);
(-)b/sys/arm/conf/BEAGLEBONE (-10 / +17 lines)
Lines 59-66 options KDB Link Here
59
options 	DDB			#Enable the kernel debugger
59
options 	DDB			#Enable the kernel debugger
60
options 	INVARIANTS		#Enable calls of extra sanity checking
60
options 	INVARIANTS		#Enable calls of extra sanity checking
61
options 	INVARIANT_SUPPORT	#Extra sanity checks of internal structures, required by INVARIANTS
61
options 	INVARIANT_SUPPORT	#Extra sanity checks of internal structures, required by INVARIANTS
62
options 	WITNESS			#Enable checks to detect deadlocks and cycles
62
#options 	WITNESS			#Enable checks to detect deadlocks and cycles
63
options 	WITNESS_SKIPSPIN	#Don't run witness on spinlocks for speed
63
#options 	WITNESS_SKIPSPIN	#Don't run witness on spinlocks for speed
64
#options 	DIAGNOSTIC
64
#options 	DIAGNOSTIC
65
65
66
# NFS support
66
# NFS support
Lines 69-80 options NFSCL Link Here
69
options 	NFSLOCKD
69
options 	NFSLOCKD
70
70
71
# Uncomment this for NFS root
71
# Uncomment this for NFS root
72
#options 	NFS_ROOT		#NFS usable as /, requires NFSCL
72
options 	NFS_ROOT		#NFS usable as /, requires NFSCL
73
#options 	BOOTP_NFSROOT
73
options 	BOOTP_NFSROOT
74
#options 	BOOTP_COMPAT
74
options 	BOOTP_COMPAT
75
#options 	BOOTP
75
options 	BOOTP
76
#options 	BOOTP_NFSV3
76
options 	BOOTP_NFSV3
77
#options 	BOOTP_WIRED_TO=cpsw0
77
options 	BOOTP_WIRED_TO=cpsw0
78
78
79
79
80
# MMC/SD/SDIO card slot support
80
# MMC/SD/SDIO card slot support
Lines 83-89 device mmcsd # mmc/sd flash cards Link Here
83
device		sdhci			# mmc/sd host controller
83
device		sdhci			# mmc/sd host controller
84
84
85
# Boot device is 2nd slice on MMC/SD card
85
# Boot device is 2nd slice on MMC/SD card
86
options 	ROOTDEVNAME=\"ufs:mmcsd0s2\"
86
#options 	ROOTDEVNAME=\"ufs:mmcsd0s2\"
87
options 	ROOTDEVNAME=\"nfs:192.168.0.123:/bbb\"
87
88
88
# Console and misc
89
# Console and misc
89
device		uart
90
device		uart
Lines 131-134 device usfs Link Here
131
# Flattened Device Tree
132
# Flattened Device Tree
132
options         FDT
133
options         FDT
133
options         FDT_DTB_STATIC
134
options         FDT_DTB_STATIC
134
makeoptions     FDT_DTS_FILE=beaglebone.dts
135
makeoptions     FDT_DTS_FILE=beaglebone-black.dts
136
137
#dtrace support
138
options 	KDTRACE_HOOKS		# Kernel DTrace hooks
139
options		DDB_CTF              	# all architectures - kernel ELF linker loads CTF data
140
makeoptions 	WITH_CTF=1
141
makeoptions     MODULES_OVERRIDE="opensolaris dtrace cyclic dtrace/dtnfsclient dtrace/dtnfscl dtrace/lockstat dtrace/profile dtrace/fbt"
(-)b/sys/arm/include/cpufunc.h (-1 / +1 lines)
Lines 167-173 struct cpu_functions { Link Here
167
extern struct cpu_functions cpufuncs;
167
extern struct cpu_functions cpufuncs;
168
extern u_int cputype;
168
extern u_int cputype;
169
169
170
#define cpu_id()		cpufuncs.cf_id()
170
#define cpu_ident()		cpufuncs.cf_id()
171
#define	cpu_cpwait()		cpufuncs.cf_cpwait()
171
#define	cpu_cpwait()		cpufuncs.cf_cpwait()
172
172
173
#define cpu_control(c, e)	cpufuncs.cf_control(c, e)
173
#define cpu_control(c, e)	cpufuncs.cf_control(c, e)
(-)b/sys/cddl/contrib/opensolaris/uts/arm/sys/fasttrap_isa.c (+30 lines)
Added Link Here
1
/*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License (the "License").
6
 * You may not use this file except in compliance with the License.
7
 *
8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9
 * or http://www.opensolaris.org/os/licensing.
10
 * See the License for the specific language governing permissions
11
 * and limitations under the License.
12
 *
13
 * When distributing Covered Code, include this CDDL HEADER in each
14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15
 * If applicable, add the following below this CDDL HEADER, with the
16
 * fields enclosed by brackets "[]" replaced with your own identifying
17
 * information: Portions Copyright [yyyy] [name of copyright owner]
18
 *
19
 * CDDL HEADER END
20
 */
21
22
/*
23
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24
 * Use is subject to license terms.
25
 */
26
27
28
/*
29
 *	XXX: Placeholder for ARM fasttrap code
30
 */
(-)b/sys/cddl/contrib/opensolaris/uts/arm/sys/fasttrap_isa.h (+94 lines)
Added Link Here
1
/*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License, Version 1.0 only
6
 * (the "License").  You may not use this file except in compliance
7
 * with the License.
8
 *
9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
 * or http://www.opensolaris.org/os/licensing.
11
 * See the License for the specific language governing permissions
12
 * and limitations under the License.
13
 *
14
 * When distributing Covered Code, include this CDDL HEADER in each
15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
 * If applicable, add the following below this CDDL HEADER, with the
17
 * fields enclosed by brackets "[]" replaced with your own identifying
18
 * information: Portions Copyright [yyyy] [name of copyright owner]
19
 *
20
 * CDDL HEADER END
21
 */
22
/*
23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24
 * Use is subject to license terms.
25
 */
26
27
#ifndef	_FASTTRAP_ISA_H
28
#define	_FASTTRAP_ISA_H
29
30
#pragma ident	"%Z%%M%	%I%	%E% SMI"
31
32
#include <sys/types.h>
33
34
#ifdef	__cplusplus
35
extern "C" {
36
#endif
37
38
/*
39
 * This is our reserved trap instruction: ta 0x38
40
 */
41
#define	FASTTRAP_INSTR			0x91d02038
42
43
#define	FASTTRAP_SUNWDTRACE_SIZE	128
44
45
typedef uint32_t	fasttrap_instr_t;
46
47
typedef struct fasttrap_machtp {
48
	fasttrap_instr_t	ftmt_instr;	/* original instruction */
49
	uintptr_t		ftmt_dest;	/* destination of DCTI */
50
	uint8_t			ftmt_type;	/* emulation type */
51
	uint8_t			ftmt_flags;	/* emulation flags */
52
	uint8_t			ftmt_cc;	/* which cc to look at */
53
	uint8_t			ftmt_code;	/* branch condition */
54
} fasttrap_machtp_t;
55
56
#define	ftt_instr	ftt_mtp.ftmt_instr
57
#define	ftt_dest	ftt_mtp.ftmt_dest
58
#define	ftt_type	ftt_mtp.ftmt_type
59
#define	ftt_flags	ftt_mtp.ftmt_flags
60
#define	ftt_cc		ftt_mtp.ftmt_cc
61
#define	ftt_code	ftt_mtp.ftmt_code
62
63
#define	FASTTRAP_T_COMMON	0x00	/* common case -- no emulation */
64
#define	FASTTRAP_T_CCR		0x01	/* integer condition code branch */
65
#define	FASTTRAP_T_FCC		0x02	/* floating-point branch */
66
#define	FASTTRAP_T_REG		0x03	/* register predicated branch */
67
#define	FASTTRAP_T_ALWAYS	0x04	/* branch always */
68
#define	FASTTRAP_T_CALL		0x05	/* call instruction */
69
#define	FASTTRAP_T_JMPL		0x06	/* jmpl instruction */
70
#define	FASTTRAP_T_RDPC		0x07	/* rdpc instruction */
71
#define	FASTTRAP_T_RETURN	0x08	/* return instruction */
72
73
/*
74
 * For performance rather than correctness.
75
 */
76
#define	FASTTRAP_T_SAVE		0x10	/* save instruction (func entry only) */
77
#define	FASTTRAP_T_RESTORE	0x11	/* restore instruction */
78
#define	FASTTRAP_T_OR		0x12	/* mov instruction */
79
#define	FASTTRAP_T_SETHI	0x13	/* sethi instruction (includes nop) */
80
81
#define	FASTTRAP_F_ANNUL	0x01	/* branch is annulled */
82
#define	FASTTRAP_F_RETMAYBE	0x02	/* not definitely a return site */
83
84
#define	FASTTRAP_AFRAMES		3
85
#define	FASTTRAP_RETURN_AFRAMES		4
86
#define	FASTTRAP_ENTRY_AFRAMES		3
87
#define	FASTTRAP_OFFSET_AFRAMES		3
88
89
90
#ifdef	__cplusplus
91
}
92
#endif
93
94
#endif	/* _FASTTRAP_ISA_H */
(-)b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c (-1 / +1 lines)
Lines 10933-10939 err: Link Here
10933
#else
10933
#else
10934
	int i;
10934
	int i;
10935
10935
10936
#if defined(__amd64__) || defined(__mips__) || defined(__powerpc__)
10936
#if defined(__amd64__) || defined(__mips__) || defined(__powerpc__) || defined(__arm__)
10937
	/*
10937
	/*
10938
	 * FreeBSD isn't good at limiting the amount of memory we
10938
	 * FreeBSD isn't good at limiting the amount of memory we
10939
	 * ask to malloc, so let's place a limit here before trying
10939
	 * ask to malloc, so let's place a limit here before trying
(-)b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h (+7 lines)
Lines 2390-2395 extern void dtrace_helpers_destroy(proc_t *); Link Here
2390
#define DTRACE_INVOP_MFLR_R0	5
2390
#define DTRACE_INVOP_MFLR_R0	5
2391
#define DTRACE_INVOP_NOP	6
2391
#define DTRACE_INVOP_NOP	6
2392
2392
2393
#elif defined(__arm__)
2394
2395
#define DTRACE_INVOP_PUSHM	1
2396
#define DTRACE_INVOP_POPM	2
2397
#define DTRACE_INVOP_B  	3
2398
2399
2393
#endif
2400
#endif
2394
2401
2395
#ifdef	__cplusplus
2402
#ifdef	__cplusplus
(-)b/sys/cddl/dev/dtrace/arm/dtrace_asm.S (+185 lines)
Added Link Here
1
/*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License, Version 1.0 only
6
 * (the "License").  You may not use this file except in compliance
7
 * with the License.
8
 *
9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
 * or http://www.opensolaris.org/os/licensing.
11
 * See the License for the specific language governing permissions
12
 * and limitations under the License.
13
 *
14
 * When distributing Covered Code, include this CDDL HEADER in each
15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
 * If applicable, add the following below this CDDL HEADER, with the
17
 * fields enclosed by brackets "[]" replaced with your own identifying
18
 * information: Portions Copyright [yyyy] [name of copyright owner]
19
 *
20
 * CDDL HEADER END
21
 *
22
 * $FreeBSD$
23
 */
24
/*
25
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
26
 * Use is subject to license terms.
27
 */
28
29
#define _ASM
30
#define _LOCORE
31
#define LOCORE
32
33
#include <sys/cpuvar_defs.h>
34
#include <sys/dtrace.h>
35
36
#include <machine/asm.h>
37
38
#include "assym.s"
39
40
/*
41
void dtrace_membar_producer(void)
42
*/
43
ENTRY(dtrace_membar_producer)
44
	RET
45
46
/*
47
void dtrace_membar_consumer(void)
48
*/
49
ENTRY(dtrace_membar_consumer)
50
	RET
51
52
/*
53
dtrace_icookie_t dtrace_interrupt_disable(void)
54
*/
55
ENTRY(dtrace_interrupt_disable)
56
	mrs	r0, cpsr
57
	mov	r1, r0
58
	orr	r1, r1, #(I32_bit|F32_bit)
59
	msr	cpsr_c, r1
60
	RET
61
/*
62
void dtrace_interrupt_enable(dtrace_icookie_t cookie)
63
*/
64
ENTRY(dtrace_interrupt_enable)
65
	and	r0, r0, #(I32_bit|F32_bit)
66
	mrs	r1, cpsr
67
	bic	r1, r1, #(I32_bit|F32_bit)
68
	orr	r1, r1, r0
69
	msr	cpsr_c, r1
70
	RET
71
72
/*
73
uint8_t
74
dtrace_fuword8_nocheck(void *addr)
75
*/
76
ENTRY(dtrace_fuword8_nocheck)
77
	ldrb	r3, [r0]
78
	mov 	r0, r3
79
	RET
80
81
/*
82
uint16_t
83
dtrace_fuword16_nocheck(void *addr)
84
*/
85
ENTRY(dtrace_fuword16_nocheck)
86
	ldrh	r3, [r0]
87
	mov 	r0, r3
88
	RET
89
90
/*
91
uint32_t
92
dtrace_fuword32_nocheck(void *addr)
93
*/
94
ENTRY(dtrace_fuword32_nocheck)
95
	ldr	r3, [r0]
96
	mov 	r0, r3
97
	RET
98
99
/*
100
uint64_t
101
dtrace_fuword64_nocheck(void *addr)
102
*/
103
ENTRY(dtrace_fuword64_nocheck)
104
	ldm	r0, {r2, r3}
105
106
	mov	r0, r2
107
	mov	r1, r3
108
#if defined(__BIG_ENDIAN__)
109
/* big endian */
110
	mov	r0, r3
111
	mov	r1, r2
112
#else
113
/* little endian */
114
	mov	r0, r2
115
	mov	r1, r3
116
117
#endif
118
	RET
119
120
/*
121
void
122
dtrace_copy(uintptr_t uaddr, uintptr_t kaddr, size_t size)
123
*/
124
ENTRY(dtrace_copy)
125
	stmfd   sp!, {r4-r5}			/* stack is 8 byte aligned */
126
	teq     r2, #0x00000000
127
	mov     r5, #0x00000000
128
	beq     2f
129
130
1:	ldrb    r4, [r0], #0x0001
131
	add     r5, r5, #0x00000001
132
	strb    r4, [r1], #0x0001
133
	teqne   r5, r2
134
	bne     1b
135
136
2:	ldmfd   sp!, {r4-r5}			/* stack is 8 byte aligned */
137
	RET
138
139
140
/*
141
void
142
dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
143
    volatile uint16_t *flags)
144
XXX: Check for flags?
145
*/
146
ENTRY(dtrace_copystr)
147
	stmfd   sp!, {r4-r5}			/* stack is 8 byte aligned */
148
	teq     r2, #0x00000000
149
	mov     r5, #0x00000000
150
	beq     2f
151
152
1:	ldrb    r4, [r0], #0x0001
153
	add     r5, r5, #0x00000001
154
	teq     r4, #0x00000000
155
	strb    r4, [r1], #0x0001
156
	teqne   r5, r2
157
	bne     1b
158
159
2:	ldmfd   sp!, {r4-r5}			/* stack is 8 byte aligned */
160
	RET
161
162
#if 0
163
/*
164
void
165
vpanic(const char *format, va_list alist)
166
*/
167
ENTRY(vpanic)				/* Initial stack layout: */
168
vpanic_common:
169
	RET
170
#endif
171
/*
172
void
173
dtrace_vpanic(const char *format, va_list alist)
174
*/
175
ENTRY(dtrace_vpanic)			/* Initial stack layout: */
176
	b	vpanic	
177
	RET
178
179
/*
180
uintptr_t
181
dtrace_caller(int aframes)
182
*/
183
ENTRY(dtrace_caller)
184
	mov	r0, #-1
185
	RET
(-)b/sys/cddl/dev/dtrace/arm/dtrace_isa.c (+373 lines)
Added Link Here
1
/*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License, Version 1.0 only
6
 * (the "License").  You may not use this file except in compliance
7
 * with the License.
8
 *
9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
 * or http://www.opensolaris.org/os/licensing.
11
 * See the License for the specific language governing permissions
12
 * and limitations under the License.
13
 *
14
 * When distributing Covered Code, include this CDDL HEADER in each
15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
 * If applicable, add the following below this CDDL HEADER, with the
17
 * fields enclosed by brackets "[]" replaced with your own identifying
18
 * information: Portions Copyright [yyyy] [name of copyright owner]
19
 *
20
 * CDDL HEADER END
21
 *
22
 * $FreeBSD$
23
 */
24
/*
25
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
26
 * Use is subject to license terms.
27
 */
28
#include <sys/cdefs.h>
29
30
#include <sys/param.h>
31
#include <sys/systm.h>
32
#include <sys/kernel.h>
33
#include <sys/stack.h>
34
#include <sys/pcpu.h>
35
36
#include <machine/frame.h>
37
#include <machine/md_var.h>
38
#include <machine/reg.h>
39
40
#include <vm/vm.h>
41
#include <vm/vm_param.h>
42
#include <vm/pmap.h>
43
44
#include <machine/atomic.h>
45
#include <machine/db_machdep.h>
46
#include <machine/md_var.h>
47
#include <machine/vmparam.h>
48
#include <machine/stack.h>
49
#include <ddb/db_sym.h>
50
#include <ddb/ddb.h>
51
#include <sys/kdb.h>
52
53
#include "regset.h"
54
55
/*
56
 * Wee need some reasonable default to prevent backtrace code
57
 * from wandering too far
58
 */
59
#define	MAX_FUNCTION_SIZE 0x10000
60
#define	MAX_PROLOGUE_SIZE 0x100
61
62
63
uint8_t dtrace_fuword8_nocheck(void *);
64
uint16_t dtrace_fuword16_nocheck(void *);
65
uint32_t dtrace_fuword32_nocheck(void *);
66
uint64_t dtrace_fuword64_nocheck(void *);
67
68
void
69
dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
70
    uint32_t *intrpc)
71
{
72
	u_int32_t	*frame, *lastframe;
73
	int	scp_offset;
74
	int	depth = 0;
75
	pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;
76
77
	if (intrpc != 0)
78
		pcstack[depth++] = (pc_t) intrpc;
79
80
	aframes++;
81
82
	frame = (u_int32_t *)__builtin_frame_address(0);;
83
	lastframe = NULL;
84
	scp_offset = -(get_pc_str_offset() >> 2);
85
86
	while ((frame != NULL) && (depth < pcstack_limit)) {
87
		db_addr_t	scp;
88
#if 0 
89
		u_int32_t	savecode;
90
		int		r;
91
		u_int32_t	*rp;
92
#endif
93
94
		/*
95
		 * In theory, the SCP isn't guaranteed to be in the function
96
		 * that generated the stack frame.  We hope for the best.
97
		 */
98
		scp = frame[FR_SCP];
99
		printf("--> %08x\n", (uint32_t)scp);
100
101
		if (aframes > 0) {
102
			aframes--;
103
			if ((aframes == 0) && (caller != 0)) {
104
				pcstack[depth++] = caller;
105
			}
106
		}
107
		else {
108
			printf("++ --> %08x\n", (uint32_t)scp);
109
			pcstack[depth++] = scp;
110
		}
111
112
#if 0
113
		savecode = ((u_int32_t *)scp)[scp_offset];
114
		if ((savecode & 0x0e100000) == 0x08000000) {
115
			/* Looks like an STM */
116
			rp = frame - 4;
117
			for (r = 10; r >= 0; r--) {
118
				if (savecode & (1 << r)) {
119
					/* register r == *rp-- */
120
				}
121
			}
122
		}
123
#endif
124
125
		/*
126
		 * Switch to next frame up
127
		 */
128
		if (frame[FR_RFP] == 0)
129
			break; /* Top of stack */
130
131
		lastframe = frame;
132
		frame = (u_int32_t *)(frame[FR_RFP]);
133
134
		if (INKERNEL((int)frame)) {
135
			/* staying in kernel */
136
			if (frame <= lastframe) {
137
				/* bad frame pointer */
138
				break;
139
			}
140
		}
141
		else
142
			break;
143
	}
144
145
	for (; depth < pcstack_limit; depth++) {
146
		pcstack[depth] = 0;
147
	}
148
}
149
150
void
151
dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
152
{
153
	printf("IMPLEMENT ME: %s\n", __func__);
154
}
155
156
int
157
dtrace_getustackdepth(void)
158
{
159
	printf("IMPLEMENT ME: %s\n", __func__);
160
	return (0);
161
}
162
163
void
164
dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
165
{
166
	printf("IMPLEMENT ME: %s\n", __func__);
167
}
168
169
/*ARGSUSED*/
170
uint64_t
171
dtrace_getarg(int arg, int aframes)
172
{
173
	struct arm_frame *fp = (struct arm_frame *)dtrace_getfp();
174
175
	return (0);
176
}
177
178
int
179
dtrace_getstackdepth(int aframes)
180
{
181
	u_int32_t	*frame, *lastframe;
182
	int	scp_offset;
183
	int	depth = 1;
184
185
	frame = (u_int32_t *)__builtin_frame_address(0);;
186
	lastframe = NULL;
187
	scp_offset = -(get_pc_str_offset() >> 2);
188
189
	while (frame != NULL) {
190
		db_addr_t	scp;
191
#if 0 
192
		u_int32_t	savecode;
193
		int		r;
194
		u_int32_t	*rp;
195
#endif
196
197
		/*
198
		 * In theory, the SCP isn't guaranteed to be in the function
199
		 * that generated the stack frame.  We hope for the best.
200
		 */
201
		scp = frame[FR_SCP];
202
203
		depth++;
204
205
		/*
206
		 * Switch to next frame up
207
		 */
208
		if (frame[FR_RFP] == 0)
209
			break; /* Top of stack */
210
211
		lastframe = frame;
212
		frame = (u_int32_t *)(frame[FR_RFP]);
213
214
		if (INKERNEL((int)frame)) {
215
			/* staying in kernel */
216
			if (frame <= lastframe) {
217
				/* bad frame pointer */
218
				break;
219
			}
220
		}
221
		else
222
			break;
223
	}
224
225
	if (depth < aframes)
226
		return 0;
227
	else
228
		return depth - aframes;
229
230
}
231
232
ulong_t
233
dtrace_getreg(struct trapframe *rp, uint_t reg)
234
{
235
	printf("IMPLEMENT ME: %s\n", __func__);
236
237
	return (0);
238
}
239
240
static int
241
dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
242
{
243
244
	if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) {
245
		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
246
		cpu_core[curcpu].cpuc_dtrace_illval = uaddr;
247
		return (0);
248
	}
249
250
	return (1);
251
}
252
253
void
254
dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
255
    volatile uint16_t *flags)
256
{
257
	if (dtrace_copycheck(uaddr, kaddr, size))
258
		dtrace_copy(uaddr, kaddr, size);
259
}
260
261
void
262
dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
263
    volatile uint16_t *flags)
264
{
265
	if (dtrace_copycheck(uaddr, kaddr, size))
266
		dtrace_copy(kaddr, uaddr, size);
267
}
268
269
void
270
dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
271
    volatile uint16_t *flags)
272
{
273
	if (dtrace_copycheck(uaddr, kaddr, size))
274
		dtrace_copystr(uaddr, kaddr, size, flags);
275
}
276
277
void
278
dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
279
    volatile uint16_t *flags)
280
{
281
	if (dtrace_copycheck(uaddr, kaddr, size))
282
		dtrace_copystr(kaddr, uaddr, size, flags);
283
}
284
285
uint8_t
286
dtrace_fuword8(void *uaddr)
287
{
288
	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
289
		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
290
		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
291
		return (0);
292
	}
293
	return (dtrace_fuword8_nocheck(uaddr));
294
}
295
296
uint16_t
297
dtrace_fuword16(void *uaddr)
298
{
299
	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
300
		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
301
		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
302
		return (0);
303
	}
304
	return (dtrace_fuword16_nocheck(uaddr));
305
}
306
307
uint32_t
308
dtrace_fuword32(void *uaddr)
309
{
310
	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
311
		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
312
		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
313
		return (0);
314
	}
315
	return (dtrace_fuword32_nocheck(uaddr));
316
}
317
318
uint64_t
319
dtrace_fuword64(void *uaddr)
320
{
321
	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
322
		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
323
		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
324
		return (0);
325
	}
326
	return (dtrace_fuword64_nocheck(uaddr));
327
}
328
329
#ifndef I32_bit
330
#define I32_bit (1 << 7)        /* IRQ disable */
331
#endif
332
#ifndef F32_bit
333
#define F32_bit (1 << 6)        /* FIQ disable */
334
#endif
335
336
#define __with_interrupts_disabled(expr) \
337
        do {                                            \
338
                u_int cpsr_save, tmp;                   \
339
                                                        \
340
                __asm __volatile(                       \
341
                        "mrs  %0, cpsr;"                \
342
                        "orr  %1, %0, %2;"              \
343
                        "msr  cpsr_all, %1;"            \
344
                        : "=r" (cpsr_save), "=r" (tmp)  \
345
                        : "I" (I32_bit | F32_bit)               \
346
                        : "cc" );               \
347
                (expr);                         \
348
                 __asm __volatile(              \
349
                        "msr  cpsr_all, %0"     \
350
                        : /* no output */       \
351
                        : "r" (cpsr_save)       \
352
                        : "cc" );               \
353
        } while(0)
354
355
uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)
356
{
357
	uint32_t ret;
358
	__with_interrupts_disabled(
359
	{
360
		ret = *target;
361
		if (*target == cmp) {
362
			*target = new;
363
		}
364
	});
365
366
	return ret;
367
}
368
369
void * dtrace_casptr(volatile void *target, volatile void *cmp, volatile void *new)
370
{
371
	return (void*)dtrace_cas32((uint32_t*)target, (uint32_t)cmp, (uint32_t)new);
372
}
373
(-)b/sys/cddl/dev/dtrace/arm/dtrace_subr.c (+264 lines)
Added Link Here
1
/*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License, Version 1.0 only
6
 * (the "License").  You may not use this file except in compliance
7
 * with the License.
8
 *
9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
 * or http://www.opensolaris.org/os/licensing.
11
 * See the License for the specific language governing permissions
12
 * and limitations under the License.
13
 *
14
 * When distributing Covered Code, include this CDDL HEADER in each
15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
 * If applicable, add the following below this CDDL HEADER, with the
17
 * fields enclosed by brackets "[]" replaced with your own identifying
18
 * information: Portions Copyright [yyyy] [name of copyright owner]
19
 *
20
 * CDDL HEADER END
21
 *
22
 * $FreeBSD$
23
 *
24
 */
25
/*
26
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
27
 * Use is subject to license terms.
28
 */
29
30
#include <sys/cdefs.h>
31
__FBSDID("$FreeBSD$");
32
33
#include <sys/param.h>
34
#include <sys/systm.h>
35
#include <sys/types.h>
36
#include <sys/kernel.h>
37
#include <sys/malloc.h>
38
#include <sys/kmem.h>
39
#include <sys/smp.h>
40
#include <sys/dtrace_impl.h>
41
#include <sys/dtrace_bsd.h>
42
#include <machine/armreg.h>
43
#include <machine/clock.h>
44
#include <machine/frame.h>
45
#include <machine/trap.h>
46
#include <vm/pmap.h>
47
48
#define	DELAYBRANCH(x)	((int)(x) < 0)
49
		
50
extern uintptr_t 	dtrace_in_probe_addr;
51
extern int		dtrace_in_probe;
52
extern dtrace_id_t	dtrace_probeid_error;
53
extern int (*dtrace_invop_jump_addr)(struct trapframe *);
54
55
int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
56
void dtrace_invop_init(void);
57
void dtrace_invop_uninit(void);
58
59
typedef struct dtrace_invop_hdlr {
60
	int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t);
61
	struct dtrace_invop_hdlr *dtih_next;
62
} dtrace_invop_hdlr_t;
63
64
dtrace_invop_hdlr_t *dtrace_invop_hdlr;
65
66
int
67
dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax)
68
{
69
	dtrace_invop_hdlr_t *hdlr;
70
	int rval;
71
72
	for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
73
		if ((rval = hdlr->dtih_func(addr, stack, eax)) != 0)
74
			return (rval);
75
76
	return (0);
77
}
78
79
80
void
81
dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
82
{
83
	dtrace_invop_hdlr_t *hdlr;
84
85
	hdlr = kmem_alloc(sizeof (dtrace_invop_hdlr_t), KM_SLEEP);
86
	hdlr->dtih_func = func;
87
	hdlr->dtih_next = dtrace_invop_hdlr;
88
	dtrace_invop_hdlr = hdlr;
89
}
90
91
void
92
dtrace_invop_remove(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
93
{
94
	dtrace_invop_hdlr_t *hdlr = dtrace_invop_hdlr, *prev = NULL;
95
96
	for (;;) {
97
		if (hdlr == NULL)
98
			panic("attempt to remove non-existent invop handler");
99
100
		if (hdlr->dtih_func == func)
101
			break;
102
103
		prev = hdlr;
104
		hdlr = hdlr->dtih_next;
105
	}
106
107
	if (prev == NULL) {
108
		ASSERT(dtrace_invop_hdlr == hdlr);
109
		dtrace_invop_hdlr = hdlr->dtih_next;
110
	} else {
111
		ASSERT(dtrace_invop_hdlr != hdlr);
112
		prev->dtih_next = hdlr->dtih_next;
113
	}
114
115
	kmem_free(hdlr, 0);
116
}
117
118
119
/*ARGSUSED*/
120
void
121
dtrace_toxic_ranges(void (*func)(uintptr_t base, uintptr_t limit))
122
{
123
	printf("IMPLEMENT ME: dtrace_toxic_ranges\n");
124
}
125
126
void
127
dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg)
128
{
129
	cpuset_t cpus;
130
131
	if (cpu == DTRACE_CPUALL)
132
		cpus = all_cpus;
133
	else
134
		CPU_SETOF(cpu, &cpus);
135
136
	smp_rendezvous_cpus(cpus, smp_no_rendevous_barrier, func,
137
	    smp_no_rendevous_barrier, arg);
138
}
139
140
static void
141
dtrace_sync_func(void)
142
{
143
}
144
145
void
146
dtrace_sync(void)
147
{
148
        dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL);
149
}
150
151
/*
152
 * DTrace needs a high resolution time function which can
153
 * be called from a probe context and guaranteed not to have
154
 * instrumented with probes itself.
155
 *
156
 * Returns nanoseconds since boot.
157
 */
158
uint64_t
159
dtrace_gethrtime()
160
{
161
	struct      timespec curtime;
162
163
	nanouptime(&curtime);
164
165
	return (curtime.tv_sec * 1000000000UL + curtime.tv_nsec);
166
167
}
168
169
uint64_t
170
dtrace_gethrestime(void)
171
{
172
	struct      timespec curtime;
173
174
	getnanotime(&curtime);
175
176
	return (curtime.tv_sec * 1000000000UL + curtime.tv_nsec);
177
}
178
179
/* Function to handle DTrace traps during probes. See amd64/amd64/trap.c */
180
int
181
dtrace_trap(struct trapframe *frame, u_int type)
182
{
183
	/*
184
	 * A trap can occur while DTrace executes a probe. Before
185
	 * executing the probe, DTrace blocks re-scheduling and sets
186
	 * a flag in it's per-cpu flags to indicate that it doesn't
187
	 * want to fault. On returning from the probe, the no-fault
188
	 * flag is cleared and finally re-scheduling is enabled.
189
	 *
190
	 * Check if DTrace has enabled 'no-fault' mode:
191
	 *
192
	 */
193
	if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
194
		/*
195
		 * There are only a couple of trap types that are expected.
196
		 * All the rest will be handled in the usual way.
197
		 */
198
		switch (type) {
199
		/* Page fault. */
200
		case FAULT_WRTBUF_0:
201
		case FAULT_WRTBUF_1:
202
		case FAULT_ALIGN_0:
203
		case FAULT_ALIGN_1:
204
			/* Flag a bad address. */
205
			cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR;
206
			cpu_core[curcpu].cpuc_dtrace_illval = 0;
207
208
			/*
209
			 * Offset the instruction pointer to the instruction
210
			 * following the one causing the fault.
211
			 */
212
			frame->tf_pc += sizeof(int);
213
			return (1);
214
		default:
215
			/* Handle all other traps in the usual way. */
216
			break;
217
		}
218
	}
219
220
	/* Handle the trap in the usual way. */
221
	return (0);
222
}
223
224
void
225
dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which,
226
    int fault, int fltoffs, uintptr_t illval)
227
{
228
229
	dtrace_probe(dtrace_probeid_error, (uint64_t)(uintptr_t)state,
230
	    (uintptr_t)epid,
231
	    (uintptr_t)which, (uintptr_t)fault, (uintptr_t)fltoffs);
232
}
233
234
static int
235
dtrace_invop_start(struct trapframe *frame)
236
{
237
	printf("IMPLEMENT ME: %s\n", __func__);
238
	switch (dtrace_invop(frame->tf_pc, (uintptr_t *)frame, frame->tf_pc)) {
239
	case DTRACE_INVOP_PUSHM:
240
		// TODO:
241
		break;
242
	case DTRACE_INVOP_POPM:
243
		// TODO:
244
		break;
245
	case DTRACE_INVOP_B:
246
		// TODO
247
		break;
248
	default:
249
		return (-1);
250
		break;
251
	}
252
253
	return (0);
254
}
255
256
void dtrace_invop_init(void)
257
{
258
	dtrace_invop_jump_addr = dtrace_invop_start;
259
}
260
261
void dtrace_invop_uninit(void)
262
{
263
	dtrace_invop_jump_addr = 0;
264
}
(-)b/sys/cddl/dev/dtrace/arm/regset.h (+56 lines)
Added Link Here
1
/*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License, Version 1.0 only
6
 * (the "License").  You may not use this file except in compliance
7
 * with the License.
8
 *
9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
 * or http://www.opensolaris.org/os/licensing.
11
 * See the License for the specific language governing permissions
12
 * and limitations under the License.
13
 *
14
 * When distributing Covered Code, include this CDDL HEADER in each
15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
 * If applicable, add the following below this CDDL HEADER, with the
17
 * fields enclosed by brackets "[]" replaced with your own identifying
18
 * information: Portions Copyright [yyyy] [name of copyright owner]
19
 *
20
 * CDDL HEADER END
21
 *
22
 * $FreeBSD$ 
23
 */
24
/*
25
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
26
 * Use is subject to license terms.
27
 */
28
29
/*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
30
31
/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T		*/
32
/*	All Rights Reserved	*/
33
34
#ifndef	_REGSET_H
35
#define	_REGSET_H
36
37
/*
38
 * #pragma ident	"@(#)regset.h	1.11	05/06/08 SMI"
39
 */
40
41
#ifdef __cplusplus
42
extern "C" {
43
#endif
44
45
#define REG_PC  R14
46
#define REG_FP  R13
47
#define REG_SP  R12
48
#define REG_PS  R0
49
#define REG_R0  R0
50
#define REG_R1  R1
51
52
#ifdef	__cplusplus
53
}
54
#endif
55
56
#endif	/* _REGSET_H */
(-)b/sys/cddl/dev/fbt/fbt_arm.c (+1303 lines)
Added Link Here
1
/*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License (the "License").
6
 * You may not use this file except in compliance with the License.
7
 *
8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9
 * or http://www.opensolaris.org/os/licensing.
10
 * See the License for the specific language governing permissions
11
 * and limitations under the License.
12
 *
13
 * When distributing Covered Code, include this CDDL HEADER in each
14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15
 * If applicable, add the following below this CDDL HEADER, with the
16
 * fields enclosed by brackets "[]" replaced with your own identifying
17
 * information: Portions Copyright [yyyy] [name of copyright owner]
18
 *
19
 * CDDL HEADER END
20
 *
21
 * Portions Copyright 2006-2008 John Birrell jb@freebsd.org
22
 * Portions Copyright 2013 Justin Hibbits jhibbits@freebsd.org
23
 * Portions Copyright 2013 Howard Su howardsu@freebsd.org
24
 *
25
 * $FreeBSD$
26
 *
27
 */
28
29
/*
30
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
31
 * Use is subject to license terms.
32
 */
33
34
#include <sys/cdefs.h>
35
#include <sys/param.h>
36
#include <sys/systm.h>
37
#include <sys/conf.h>
38
#include <sys/cpuvar.h>
39
#include <sys/fcntl.h>
40
#include <sys/filio.h>
41
#include <sys/kdb.h>
42
#include <sys/kernel.h>
43
#include <sys/kmem.h>
44
#include <sys/kthread.h>
45
#include <sys/limits.h>
46
#include <sys/linker.h>
47
#include <sys/lock.h>
48
#include <sys/malloc.h>
49
#include <sys/module.h>
50
#include <sys/mutex.h>
51
#include <sys/pcpu.h>
52
#include <sys/poll.h>
53
#include <sys/proc.h>
54
#include <sys/selinfo.h>
55
#include <sys/smp.h>
56
#include <sys/syscall.h>
57
#include <sys/sysent.h>
58
#include <sys/sysproto.h>
59
#include <sys/uio.h>
60
#include <sys/unistd.h>
61
#include <machine/frame.h>
62
#include <machine/md_var.h>
63
#include <machine/stdarg.h>
64
65
#include <sys/dtrace.h>
66
#include <sys/dtrace_bsd.h>
67
68
static MALLOC_DEFINE(M_FBT, "fbt", "Function Boundary Tracing");
69
70
#define FBT_PATCHVAL		0xe06a0cfe // illegal instruction
71
72
#define FBT_PUSHM		0xe92d0000
73
#define FBT_POPM		0xe8bd0000
74
#define FBT_JUMP		0xea000000
75
76
static d_open_t	fbt_open;
77
static int	fbt_unload(void);
78
static void	fbt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
79
static void	fbt_provide_module(void *, modctl_t *);
80
static void	fbt_destroy(void *, dtrace_id_t, void *);
81
static void	fbt_enable(void *, dtrace_id_t, void *);
82
static void	fbt_disable(void *, dtrace_id_t, void *);
83
static void	fbt_load(void *);
84
static void	fbt_suspend(void *, dtrace_id_t, void *);
85
static void	fbt_resume(void *, dtrace_id_t, void *);
86
87
#define	FBT_ENTRY	"entry"
88
#define	FBT_RETURN	"return"
89
#define	FBT_ADDR2NDX(addr)	((((uintptr_t)(addr)) >> 4) & fbt_probetab_mask)
90
#define	FBT_PROBETAB_SIZE	0x8000		/* 32k entries -- 128K total */
91
92
static struct cdevsw fbt_cdevsw = {
93
	.d_version	= D_VERSION,
94
	.d_open		= fbt_open,
95
	.d_name		= "fbt",
96
};
97
98
static dtrace_pattr_t fbt_attr = {
99
{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
100
{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
101
{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
102
{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
103
{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
104
};
105
106
static dtrace_pops_t fbt_pops = {
107
	NULL,
108
	fbt_provide_module,
109
	fbt_enable,
110
	fbt_disable,
111
	fbt_suspend,
112
	fbt_resume,
113
	fbt_getargdesc,
114
	NULL,
115
	NULL,
116
	fbt_destroy
117
};
118
119
typedef struct fbt_probe {
120
	struct fbt_probe *fbtp_hashnext;
121
	uint32_t	*fbtp_patchpoint;
122
	int8_t		fbtp_rval;
123
	uint32_t	fbtp_patchval;
124
	uint32_t	fbtp_savedval;
125
	uintptr_t	fbtp_roffset;
126
	dtrace_id_t	fbtp_id;
127
	const char	*fbtp_name;
128
	modctl_t	*fbtp_ctl;
129
	int		fbtp_loadcnt;
130
	int		fbtp_primary;
131
	int		fbtp_invop_cnt;
132
	int		fbtp_symindx;
133
	struct fbt_probe *fbtp_next;
134
} fbt_probe_t;
135
136
static struct cdev		*fbt_cdev;
137
static dtrace_provider_id_t	fbt_id;
138
static fbt_probe_t		**fbt_probetab;
139
static int			fbt_probetab_size;
140
static int			fbt_probetab_mask;
141
static int			fbt_verbose = 0;
142
143
static int
144
fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
145
{
146
	struct trapframe *frame = (struct trapframe *)stack;
147
	solaris_cpu_t *cpu = &solaris_cpu[curcpu];
148
	fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
149
150
	for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
151
		if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
152
			fbt->fbtp_invop_cnt++;
153
			cpu->cpu_dtrace_caller = addr;
154
155
			dtrace_probe(fbt->fbtp_id, frame->tf_r0,
156
			    frame->tf_r1, frame->tf_r2,
157
			    frame->tf_r3, 0); // TODO: Need 5th parameter from stack
158
159
			cpu->cpu_dtrace_caller = 0;
160
161
			return (fbt->fbtp_rval);
162
		}
163
	}
164
165
	return (0);
166
}
167
168
static int
169
fbt_provide_module_function(linker_file_t lf, int symindx,
170
    linker_symval_t *symval, void *opaque)
171
{
172
	char *modname = opaque;
173
	const char *name = symval->name;
174
	fbt_probe_t *fbt, *retfbt;
175
	int popm;
176
	u_int32_t *instr, *limit;
177
178
	if (strncmp(name, "dtrace_", 7) == 0 &&
179
	    strncmp(name, "dtrace_safe_", 12) != 0) {
180
		/*
181
		 * Anything beginning with "dtrace_" may be called
182
		 * from probe context unless it explicitly indicates
183
		 * that it won't be called from probe context by
184
		 * using the prefix "dtrace_safe_".
185
		 */
186
		return (0);
187
	}
188
189
	if (name[0] == '_' && name[1] == '_')
190
		return (0);
191
192
	instr = (u_int32_t *) symval->value;
193
	limit = (u_int32_t *)(symval->value + symval->size);
194
195
	for (; instr < limit; instr++)
196
		if ((*instr & 0xffff0000) == FBT_PUSHM && (*instr & 0x4000) != 0)
197
			break;
198
199
	if (instr >= limit)
200
		return (0);
201
202
	fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
203
	fbt->fbtp_name = name;
204
	fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
205
	    name, FBT_ENTRY, 3, fbt);
206
	fbt->fbtp_patchpoint = instr;
207
	fbt->fbtp_ctl = lf;
208
	fbt->fbtp_loadcnt = lf->loadcnt;
209
	fbt->fbtp_savedval = *instr;
210
	fbt->fbtp_patchval = FBT_PATCHVAL;
211
	fbt->fbtp_rval = DTRACE_INVOP_PUSHM;
212
	fbt->fbtp_symindx = symindx;
213
214
	fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
215
	fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
216
217
	lf->fbt_nentries++;
218
219
	popm = FBT_POPM | ((*instr) & 0x3FFF) | 0x8000;
220
221
222
	retfbt = NULL;
223
again:	
224
	for(; instr < limit; instr++)
225
	{
226
		if  (*instr == popm)
227
			break;
228
		else if ((*instr & 0xff000000) == FBT_JUMP)
229
		{
230
			int offset;
231
			u_int32_t *target, *start;
232
			offset = (*instr & 0xffffff);
233
			offset <<= 8;
234
			offset /= 64;
235
			target = instr + (2 + offset);
236
			start = (u_int32_t *) symval->value;
237
			if (target >= limit || target < start)
238
				break;
239
			instr++; //skip delay slot
240
		}
241
	}
242
243
	if (instr >= limit)
244
		return (0);
245
246
	/*
247
	 * We have a winner!
248
	 */
249
	fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
250
	fbt->fbtp_name = name;
251
	if (retfbt == NULL) {
252
		fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
253
		    name, FBT_RETURN, 5, fbt);
254
	} else {
255
		retfbt->fbtp_next = fbt;
256
		fbt->fbtp_id = retfbt->fbtp_id;
257
	}
258
	retfbt = fbt;
259
260
	fbt->fbtp_patchpoint = instr;
261
	fbt->fbtp_ctl = lf;
262
	fbt->fbtp_loadcnt = lf->loadcnt;
263
	fbt->fbtp_symindx = symindx;
264
	if ((*instr & 0xff000000) == FBT_JUMP)
265
		fbt->fbtp_rval = DTRACE_INVOP_B;
266
	else	
267
		fbt->fbtp_rval = DTRACE_INVOP_POPM;
268
	fbt->fbtp_savedval = *instr;
269
	fbt->fbtp_patchval = FBT_PATCHVAL;
270
	fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
271
	fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
272
273
	lf->fbt_nentries++;
274
275
	instr++;
276
	goto again;
277
}
278
279
static void
280
fbt_provide_module(void *arg, modctl_t *lf)
281
{
282
	char modname[MAXPATHLEN];
283
	int i;
284
	size_t len;
285
286
	strlcpy(modname, lf->filename, sizeof(modname));
287
	len = strlen(modname);
288
	if (len > 3 && strcmp(modname + len - 3, ".ko") == 0)
289
		modname[len - 3] = '\0';
290
291
	/*
292
	 * Employees of dtrace and their families are ineligible.  Void
293
	 * where prohibited.
294
	 */
295
	if (strcmp(modname, "dtrace") == 0)
296
		return;
297
298
	/*
299
	 * The cyclic timer subsystem can be built as a module and DTrace
300
	 * depends on that, so it is ineligible too.
301
	 */
302
	if (strcmp(modname, "cyclic") == 0)
303
		return;
304
305
	/*
306
	 * To register with DTrace, a module must list 'dtrace' as a
307
	 * dependency in order for the kernel linker to resolve
308
	 * symbols like dtrace_register(). All modules with such a
309
	 * dependency are ineligible for FBT tracing.
310
	 */
311
	for (i = 0; i < lf->ndeps; i++)
312
		if (strncmp(lf->deps[i]->filename, "dtrace", 6) == 0)
313
			return;
314
315
	if (lf->fbt_nentries) {
316
		/*
317
		 * This module has some FBT entries allocated; we're afraid
318
		 * to screw with it.
319
		 */
320
		return;
321
	}
322
323
	/*
324
	 * List the functions in the module and the symbol values.
325
	 */
326
	(void) linker_file_function_listall(lf, fbt_provide_module_function, modname);
327
}
328
329
static void
330
fbt_destroy(void *arg, dtrace_id_t id, void *parg)
331
{
332
	fbt_probe_t *fbt = parg, *next, *hash, *last;
333
	modctl_t *ctl;
334
	int ndx;
335
336
	do {
337
		ctl = fbt->fbtp_ctl;
338
339
		ctl->fbt_nentries--;
340
341
		/*
342
		 * Now we need to remove this probe from the fbt_probetab.
343
		 */
344
		ndx = FBT_ADDR2NDX(fbt->fbtp_patchpoint);
345
		last = NULL;
346
		hash = fbt_probetab[ndx];
347
348
		while (hash != fbt) {
349
			ASSERT(hash != NULL);
350
			last = hash;
351
			hash = hash->fbtp_hashnext;
352
		}
353
354
		if (last != NULL) {
355
			last->fbtp_hashnext = fbt->fbtp_hashnext;
356
		} else {
357
			fbt_probetab[ndx] = fbt->fbtp_hashnext;
358
		}
359
360
		next = fbt->fbtp_next;
361
		free(fbt, M_FBT);
362
363
		fbt = next;
364
	} while (fbt != NULL);
365
}
366
367
static void
368
fbt_enable(void *arg, dtrace_id_t id, void *parg)
369
{
370
	fbt_probe_t *fbt = parg;
371
	modctl_t *ctl = fbt->fbtp_ctl;
372
373
	ctl->nenabled++;
374
375
	/*
376
	 * Now check that our modctl has the expected load count.  If it
377
	 * doesn't, this module must have been unloaded and reloaded -- and
378
	 * we're not going to touch it.
379
	 */
380
	if (ctl->loadcnt != fbt->fbtp_loadcnt) {
381
		if (fbt_verbose) {
382
			printf("fbt is failing for probe %s "
383
			    "(module %s reloaded)",
384
			    fbt->fbtp_name, ctl->filename);
385
		}
386
387
		return;
388
	}
389
390
	for (; fbt != NULL; fbt = fbt->fbtp_next) {
391
		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
392
		cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4);
393
	}
394
}
395
396
static void
397
fbt_disable(void *arg, dtrace_id_t id, void *parg)
398
{
399
	fbt_probe_t *fbt = parg;
400
	modctl_t *ctl = fbt->fbtp_ctl;
401
402
	ASSERT(ctl->nenabled > 0);
403
	ctl->nenabled--;
404
405
	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
406
		return;
407
408
	for (; fbt != NULL; fbt = fbt->fbtp_next) {
409
		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
410
		cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4);
411
	}
412
}
413
414
static void
415
fbt_suspend(void *arg, dtrace_id_t id, void *parg)
416
{
417
	fbt_probe_t *fbt = parg;
418
	modctl_t *ctl = fbt->fbtp_ctl;
419
420
	ASSERT(ctl->nenabled > 0);
421
422
	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
423
		return;
424
425
	for (; fbt != NULL; fbt = fbt->fbtp_next) {
426
		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
427
		cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4);
428
	}
429
}
430
431
static void
432
fbt_resume(void *arg, dtrace_id_t id, void *parg)
433
{
434
	fbt_probe_t *fbt = parg;
435
	modctl_t *ctl = fbt->fbtp_ctl;
436
437
	ASSERT(ctl->nenabled > 0);
438
439
	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
440
		return;
441
442
	for (; fbt != NULL; fbt = fbt->fbtp_next) {
443
		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
444
		cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4);
445
	}
446
}
447
448
static int
449
fbt_ctfoff_init(modctl_t *lf, linker_ctf_t *lc)
450
{
451
	const Elf_Sym *symp = lc->symtab;;
452
	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
453
	const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t);
454
	int i;
455
	uint32_t *ctfoff;
456
	uint32_t objtoff = hp->cth_objtoff;
457
	uint32_t funcoff = hp->cth_funcoff;
458
	ushort_t info;
459
	ushort_t vlen;
460
461
	/* Sanity check. */
462
	if (hp->cth_magic != CTF_MAGIC) {
463
		printf("Bad magic value in CTF data of '%s'\n",lf->pathname);
464
		return (EINVAL);
465
	}
466
467
	if (lc->symtab == NULL) {
468
		printf("No symbol table in '%s'\n",lf->pathname);
469
		return (EINVAL);
470
	}
471
472
	if ((ctfoff = malloc(sizeof(uint32_t) * lc->nsym, M_LINKER, M_WAITOK)) == NULL)
473
		return (ENOMEM);
474
475
	*lc->ctfoffp = ctfoff;
476
477
	for (i = 0; i < lc->nsym; i++, ctfoff++, symp++) {
478
		if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) {
479
			*ctfoff = 0xffffffff;
480
			continue;
481
		}
482
483
		switch (ELF_ST_TYPE(symp->st_info)) {
484
		case STT_OBJECT:
485
			if (objtoff >= hp->cth_funcoff ||
486
                            (symp->st_shndx == SHN_ABS && symp->st_value == 0)) {
487
				*ctfoff = 0xffffffff;
488
                                break;
489
                        }
490
491
                        *ctfoff = objtoff;
492
                        objtoff += sizeof (ushort_t);
493
			break;
494
495
		case STT_FUNC:
496
			if (funcoff >= hp->cth_typeoff) {
497
				*ctfoff = 0xffffffff;
498
				break;
499
			}
500
501
			*ctfoff = funcoff;
502
503
			info = *((const ushort_t *)(ctfdata + funcoff));
504
			vlen = CTF_INFO_VLEN(info);
505
506
			/*
507
			 * If we encounter a zero pad at the end, just skip it.
508
			 * Otherwise skip over the function and its return type
509
			 * (+2) and the argument list (vlen).
510
			 */
511
			if (CTF_INFO_KIND(info) == CTF_K_UNKNOWN && vlen == 0)
512
				funcoff += sizeof (ushort_t); /* skip pad */
513
			else
514
				funcoff += sizeof (ushort_t) * (vlen + 2);
515
			break;
516
517
		default:
518
			*ctfoff = 0xffffffff;
519
			break;
520
		}
521
	}
522
523
	return (0);
524
}
525
526
static ssize_t
527
fbt_get_ctt_size(uint8_t version, const ctf_type_t *tp, ssize_t *sizep,
528
    ssize_t *incrementp)
529
{
530
	ssize_t size, increment;
531
532
	if (version > CTF_VERSION_1 &&
533
	    tp->ctt_size == CTF_LSIZE_SENT) {
534
		size = CTF_TYPE_LSIZE(tp);
535
		increment = sizeof (ctf_type_t);
536
	} else {
537
		size = tp->ctt_size;
538
		increment = sizeof (ctf_stype_t);
539
	}
540
541
	if (sizep)
542
		*sizep = size;
543
	if (incrementp)
544
		*incrementp = increment;
545
546
	return (size);
547
}
548
549
static int
550
fbt_typoff_init(linker_ctf_t *lc)
551
{
552
	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
553
	const ctf_type_t *tbuf;
554
	const ctf_type_t *tend;
555
	const ctf_type_t *tp;
556
	const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t);
557
	int ctf_typemax = 0;
558
	uint32_t *xp;
559
	ulong_t pop[CTF_K_MAX + 1] = { 0 };
560
561
562
	/* Sanity check. */
563
	if (hp->cth_magic != CTF_MAGIC)
564
		return (EINVAL);
565
566
	tbuf = (const ctf_type_t *) (ctfdata + hp->cth_typeoff);
567
	tend = (const ctf_type_t *) (ctfdata + hp->cth_stroff);
568
569
	int child = hp->cth_parname != 0;
570
571
	/*
572
	 * We make two passes through the entire type section.  In this first
573
	 * pass, we count the number of each type and the total number of types.
574
	 */
575
	for (tp = tbuf; tp < tend; ctf_typemax++) {
576
		ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
577
		ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
578
		ssize_t size, increment;
579
580
		size_t vbytes;
581
		uint_t n;
582
583
		(void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
584
585
		switch (kind) {
586
		case CTF_K_INTEGER:
587
		case CTF_K_FLOAT:
588
			vbytes = sizeof (uint_t);
589
			break;
590
		case CTF_K_ARRAY:
591
			vbytes = sizeof (ctf_array_t);
592
			break;
593
		case CTF_K_FUNCTION:
594
			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
595
			break;
596
		case CTF_K_STRUCT:
597
		case CTF_K_UNION:
598
			if (size < CTF_LSTRUCT_THRESH) {
599
				ctf_member_t *mp = (ctf_member_t *)
600
				    ((uintptr_t)tp + increment);
601
602
				vbytes = sizeof (ctf_member_t) * vlen;
603
				for (n = vlen; n != 0; n--, mp++)
604
					child |= CTF_TYPE_ISCHILD(mp->ctm_type);
605
			} else {
606
				ctf_lmember_t *lmp = (ctf_lmember_t *)
607
				    ((uintptr_t)tp + increment);
608
609
				vbytes = sizeof (ctf_lmember_t) * vlen;
610
				for (n = vlen; n != 0; n--, lmp++)
611
					child |=
612
					    CTF_TYPE_ISCHILD(lmp->ctlm_type);
613
			}
614
			break;
615
		case CTF_K_ENUM:
616
			vbytes = sizeof (ctf_enum_t) * vlen;
617
			break;
618
		case CTF_K_FORWARD:
619
			/*
620
			 * For forward declarations, ctt_type is the CTF_K_*
621
			 * kind for the tag, so bump that population count too.
622
			 * If ctt_type is unknown, treat the tag as a struct.
623
			 */
624
			if (tp->ctt_type == CTF_K_UNKNOWN ||
625
			    tp->ctt_type >= CTF_K_MAX)
626
				pop[CTF_K_STRUCT]++;
627
			else
628
				pop[tp->ctt_type]++;
629
			/*FALLTHRU*/
630
		case CTF_K_UNKNOWN:
631
			vbytes = 0;
632
			break;
633
		case CTF_K_POINTER:
634
		case CTF_K_TYPEDEF:
635
		case CTF_K_VOLATILE:
636
		case CTF_K_CONST:
637
		case CTF_K_RESTRICT:
638
			child |= CTF_TYPE_ISCHILD(tp->ctt_type);
639
			vbytes = 0;
640
			break;
641
		default:
642
			printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind);
643
			return (EIO);
644
		}
645
		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
646
		pop[kind]++;
647
	}
648
649
	/* account for a sentinel value below */
650
	ctf_typemax++;
651
	*lc->typlenp = ctf_typemax;
652
653
	if ((xp = malloc(sizeof(uint32_t) * ctf_typemax, M_LINKER, M_ZERO | M_WAITOK)) == NULL)
654
		return (ENOMEM);
655
656
	*lc->typoffp = xp;
657
658
	/* type id 0 is used as a sentinel value */
659
	*xp++ = 0;
660
661
	/*
662
	 * In the second pass, fill in the type offset.
663
	 */
664
	for (tp = tbuf; tp < tend; xp++) {
665
		ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
666
		ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
667
		ssize_t size, increment;
668
669
		size_t vbytes;
670
		uint_t n;
671
672
		(void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
673
674
		switch (kind) {
675
		case CTF_K_INTEGER:
676
		case CTF_K_FLOAT:
677
			vbytes = sizeof (uint_t);
678
			break;
679
		case CTF_K_ARRAY:
680
			vbytes = sizeof (ctf_array_t);
681
			break;
682
		case CTF_K_FUNCTION:
683
			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
684
			break;
685
		case CTF_K_STRUCT:
686
		case CTF_K_UNION:
687
			if (size < CTF_LSTRUCT_THRESH) {
688
				ctf_member_t *mp = (ctf_member_t *)
689
				    ((uintptr_t)tp + increment);
690
691
				vbytes = sizeof (ctf_member_t) * vlen;
692
				for (n = vlen; n != 0; n--, mp++)
693
					child |= CTF_TYPE_ISCHILD(mp->ctm_type);
694
			} else {
695
				ctf_lmember_t *lmp = (ctf_lmember_t *)
696
				    ((uintptr_t)tp + increment);
697
698
				vbytes = sizeof (ctf_lmember_t) * vlen;
699
				for (n = vlen; n != 0; n--, lmp++)
700
					child |=
701
					    CTF_TYPE_ISCHILD(lmp->ctlm_type);
702
			}
703
			break;
704
		case CTF_K_ENUM:
705
			vbytes = sizeof (ctf_enum_t) * vlen;
706
			break;
707
		case CTF_K_FORWARD:
708
		case CTF_K_UNKNOWN:
709
			vbytes = 0;
710
			break;
711
		case CTF_K_POINTER:
712
		case CTF_K_TYPEDEF:
713
		case CTF_K_VOLATILE:
714
		case CTF_K_CONST:
715
		case CTF_K_RESTRICT:
716
			vbytes = 0;
717
			break;
718
		default:
719
			printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind);
720
			return (EIO);
721
		}
722
		*xp = (uint32_t)((uintptr_t) tp - (uintptr_t) ctfdata);
723
		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
724
	}
725
726
	return (0);
727
}
728
729
/*
730
 * CTF Declaration Stack
731
 *
732
 * In order to implement ctf_type_name(), we must convert a type graph back
733
 * into a C type declaration.  Unfortunately, a type graph represents a storage
734
 * class ordering of the type whereas a type declaration must obey the C rules
735
 * for operator precedence, and the two orderings are frequently in conflict.
736
 * For example, consider these CTF type graphs and their C declarations:
737
 *
738
 * CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER  : int (*)()
739
 * CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER     : int (*)[]
740
 *
741
 * In each case, parentheses are used to raise operator * to higher lexical
742
 * precedence, so the string form of the C declaration cannot be constructed by
743
 * walking the type graph links and forming the string from left to right.
744
 *
745
 * The functions in this file build a set of stacks from the type graph nodes
746
 * corresponding to the C operator precedence levels in the appropriate order.
747
 * The code in ctf_type_name() can then iterate over the levels and nodes in
748
 * lexical precedence order and construct the final C declaration string.
749
 */
750
typedef struct ctf_list {
751
	struct ctf_list *l_prev; /* previous pointer or tail pointer */
752
	struct ctf_list *l_next; /* next pointer or head pointer */
753
} ctf_list_t;
754
755
#define	ctf_list_prev(elem)	((void *)(((ctf_list_t *)(elem))->l_prev))
756
#define	ctf_list_next(elem)	((void *)(((ctf_list_t *)(elem))->l_next))
757
758
typedef enum {
759
	CTF_PREC_BASE,
760
	CTF_PREC_POINTER,
761
	CTF_PREC_ARRAY,
762
	CTF_PREC_FUNCTION,
763
	CTF_PREC_MAX
764
} ctf_decl_prec_t;
765
766
typedef struct ctf_decl_node {
767
	ctf_list_t cd_list;			/* linked list pointers */
768
	ctf_id_t cd_type;			/* type identifier */
769
	uint_t cd_kind;				/* type kind */
770
	uint_t cd_n;				/* type dimension if array */
771
} ctf_decl_node_t;
772
773
typedef struct ctf_decl {
774
	ctf_list_t cd_nodes[CTF_PREC_MAX];	/* declaration node stacks */
775
	int cd_order[CTF_PREC_MAX];		/* storage order of decls */
776
	ctf_decl_prec_t cd_qualp;		/* qualifier precision */
777
	ctf_decl_prec_t cd_ordp;		/* ordered precision */
778
	char *cd_buf;				/* buffer for output */
779
	char *cd_ptr;				/* buffer location */
780
	char *cd_end;				/* buffer limit */
781
	size_t cd_len;				/* buffer space required */
782
	int cd_err;				/* saved error value */
783
} ctf_decl_t;
784
785
/*
786
 * Simple doubly-linked list append routine.  This implementation assumes that
787
 * each list element contains an embedded ctf_list_t as the first member.
788
 * An additional ctf_list_t is used to store the head (l_next) and tail
789
 * (l_prev) pointers.  The current head and tail list elements have their
790
 * previous and next pointers set to NULL, respectively.
791
 */
792
static void
793
ctf_list_append(ctf_list_t *lp, void *new)
794
{
795
	ctf_list_t *p = lp->l_prev;	/* p = tail list element */
796
	ctf_list_t *q = new;		/* q = new list element */
797
798
	lp->l_prev = q;
799
	q->l_prev = p;
800
	q->l_next = NULL;
801
802
	if (p != NULL)
803
		p->l_next = q;
804
	else
805
		lp->l_next = q;
806
}
807
808
/*
809
 * Prepend the specified existing element to the given ctf_list_t.  The
810
 * existing pointer should be pointing at a struct with embedded ctf_list_t.
811
 */
812
static void
813
ctf_list_prepend(ctf_list_t *lp, void *new)
814
{
815
	ctf_list_t *p = new;		/* p = new list element */
816
	ctf_list_t *q = lp->l_next;	/* q = head list element */
817
818
	lp->l_next = p;
819
	p->l_prev = NULL;
820
	p->l_next = q;
821
822
	if (q != NULL)
823
		q->l_prev = p;
824
	else
825
		lp->l_prev = p;
826
}
827
828
static void
829
ctf_decl_init(ctf_decl_t *cd, char *buf, size_t len)
830
{
831
	int i;
832
833
	bzero(cd, sizeof (ctf_decl_t));
834
835
	for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
836
		cd->cd_order[i] = CTF_PREC_BASE - 1;
837
838
	cd->cd_qualp = CTF_PREC_BASE;
839
	cd->cd_ordp = CTF_PREC_BASE;
840
841
	cd->cd_buf = buf;
842
	cd->cd_ptr = buf;
843
	cd->cd_end = buf + len;
844
}
845
846
static void
847
ctf_decl_fini(ctf_decl_t *cd)
848
{
849
	ctf_decl_node_t *cdp, *ndp;
850
	int i;
851
852
	for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) {
853
		for (cdp = ctf_list_next(&cd->cd_nodes[i]);
854
		    cdp != NULL; cdp = ndp) {
855
			ndp = ctf_list_next(cdp);
856
			free(cdp, M_FBT);
857
		}
858
	}
859
}
860
861
static const ctf_type_t *
862
ctf_lookup_by_id(linker_ctf_t *lc, ctf_id_t type)
863
{
864
	const ctf_type_t *tp;
865
	uint32_t offset;
866
	uint32_t *typoff = *lc->typoffp;
867
868
	if (type >= *lc->typlenp) {
869
		printf("%s(%d): type %d exceeds max %ld\n",__func__,__LINE__,(int) type,*lc->typlenp);
870
		return(NULL);
871
	}
872
873
	/* Check if the type isn't cross-referenced. */
874
	if ((offset = typoff[type]) == 0) {
875
		printf("%s(%d): type %d isn't cross referenced\n",__func__,__LINE__, (int) type);
876
		return(NULL);
877
	}
878
879
	tp = (const ctf_type_t *)(lc->ctftab + offset + sizeof(ctf_header_t));
880
881
	return (tp);
882
}
883
884
static void
885
fbt_array_info(linker_ctf_t *lc, ctf_id_t type, ctf_arinfo_t *arp)
886
{
887
	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
888
	const ctf_type_t *tp;
889
	const ctf_array_t *ap;
890
	ssize_t increment;
891
892
	bzero(arp, sizeof(*arp));
893
894
	if ((tp = ctf_lookup_by_id(lc, type)) == NULL)
895
		return;
896
897
	if (CTF_INFO_KIND(tp->ctt_info) != CTF_K_ARRAY)
898
		return;
899
900
	(void) fbt_get_ctt_size(hp->cth_version, tp, NULL, &increment);
901
902
	ap = (const ctf_array_t *)((uintptr_t)tp + increment);
903
	arp->ctr_contents = ap->cta_contents;
904
	arp->ctr_index = ap->cta_index;
905
	arp->ctr_nelems = ap->cta_nelems;
906
}
907
908
static const char *
909
ctf_strptr(linker_ctf_t *lc, int name)
910
{
911
	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;;
912
	const char *strp = "";
913
914
	if (name < 0 || name >= hp->cth_strlen)
915
		return(strp);
916
917
	strp = (const char *)(lc->ctftab + hp->cth_stroff + name + sizeof(ctf_header_t));
918
919
	return (strp);
920
}
921
922
static void
923
ctf_decl_push(ctf_decl_t *cd, linker_ctf_t *lc, ctf_id_t type)
924
{
925
	ctf_decl_node_t *cdp;
926
	ctf_decl_prec_t prec;
927
	uint_t kind, n = 1;
928
	int is_qual = 0;
929
930
	const ctf_type_t *tp;
931
	ctf_arinfo_t ar;
932
933
	if ((tp = ctf_lookup_by_id(lc, type)) == NULL) {
934
		cd->cd_err = ENOENT;
935
		return;
936
	}
937
938
	switch (kind = CTF_INFO_KIND(tp->ctt_info)) {
939
	case CTF_K_ARRAY:
940
		fbt_array_info(lc, type, &ar);
941
		ctf_decl_push(cd, lc, ar.ctr_contents);
942
		n = ar.ctr_nelems;
943
		prec = CTF_PREC_ARRAY;
944
		break;
945
946
	case CTF_K_TYPEDEF:
947
		if (ctf_strptr(lc, tp->ctt_name)[0] == '\0') {
948
			ctf_decl_push(cd, lc, tp->ctt_type);
949
			return;
950
		}
951
		prec = CTF_PREC_BASE;
952
		break;
953
954
	case CTF_K_FUNCTION:
955
		ctf_decl_push(cd, lc, tp->ctt_type);
956
		prec = CTF_PREC_FUNCTION;
957
		break;
958
959
	case CTF_K_POINTER:
960
		ctf_decl_push(cd, lc, tp->ctt_type);
961
		prec = CTF_PREC_POINTER;
962
		break;
963
964
	case CTF_K_VOLATILE:
965
	case CTF_K_CONST:
966
	case CTF_K_RESTRICT:
967
		ctf_decl_push(cd, lc, tp->ctt_type);
968
		prec = cd->cd_qualp;
969
		is_qual++;
970
		break;
971
972
	default:
973
		prec = CTF_PREC_BASE;
974
	}
975
976
	if ((cdp = malloc(sizeof (ctf_decl_node_t), M_FBT, M_WAITOK)) == NULL) {
977
		cd->cd_err = EAGAIN;
978
		return;
979
	}
980
981
	cdp->cd_type = type;
982
	cdp->cd_kind = kind;
983
	cdp->cd_n = n;
984
985
	if (ctf_list_next(&cd->cd_nodes[prec]) == NULL)
986
		cd->cd_order[prec] = cd->cd_ordp++;
987
988
	/*
989
	 * Reset cd_qualp to the highest precedence level that we've seen so
990
	 * far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER).
991
	 */
992
	if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY)
993
		cd->cd_qualp = prec;
994
995
	/*
996
	 * C array declarators are ordered inside out so prepend them.  Also by
997
	 * convention qualifiers of base types precede the type specifier (e.g.
998
	 * const int vs. int const) even though the two forms are equivalent.
999
	 */
1000
	if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE))
1001
		ctf_list_prepend(&cd->cd_nodes[prec], cdp);
1002
	else
1003
		ctf_list_append(&cd->cd_nodes[prec], cdp);
1004
}
1005
1006
static void
1007
ctf_decl_sprintf(ctf_decl_t *cd, const char *format, ...)
1008
{
1009
	size_t len = (size_t)(cd->cd_end - cd->cd_ptr);
1010
	va_list ap;
1011
	size_t n;
1012
1013
	va_start(ap, format);
1014
	n = vsnprintf(cd->cd_ptr, len, format, ap);
1015
	va_end(ap);
1016
1017
	cd->cd_ptr += MIN(n, len);
1018
	cd->cd_len += n;
1019
}
1020
1021
static ssize_t
1022
fbt_type_name(linker_ctf_t *lc, ctf_id_t type, char *buf, size_t len)
1023
{
1024
	ctf_decl_t cd;
1025
	ctf_decl_node_t *cdp;
1026
	ctf_decl_prec_t prec, lp, rp;
1027
	int ptr, arr;
1028
	uint_t k;
1029
1030
	if (lc == NULL && type == CTF_ERR)
1031
		return (-1); /* simplify caller code by permitting CTF_ERR */
1032
1033
	ctf_decl_init(&cd, buf, len);
1034
	ctf_decl_push(&cd, lc, type);
1035
1036
	if (cd.cd_err != 0) {
1037
		ctf_decl_fini(&cd);
1038
		return (-1);
1039
	}
1040
1041
	/*
1042
	 * If the type graph's order conflicts with lexical precedence order
1043
	 * for pointers or arrays, then we need to surround the declarations at
1044
	 * the corresponding lexical precedence with parentheses.  This can
1045
	 * result in either a parenthesized pointer (*) as in int (*)() or
1046
	 * int (*)[], or in a parenthesized pointer and array as in int (*[])().
1047
	 */
1048
	ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
1049
	arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
1050
1051
	rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
1052
	lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
1053
1054
	k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
1055
1056
	for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
1057
		for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
1058
		    cdp != NULL; cdp = ctf_list_next(cdp)) {
1059
1060
			const ctf_type_t *tp =
1061
			    ctf_lookup_by_id(lc, cdp->cd_type);
1062
			const char *name = ctf_strptr(lc, tp->ctt_name);
1063
1064
			if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
1065
				ctf_decl_sprintf(&cd, " ");
1066
1067
			if (lp == prec) {
1068
				ctf_decl_sprintf(&cd, "(");
1069
				lp = -1;
1070
			}
1071
1072
			switch (cdp->cd_kind) {
1073
			case CTF_K_INTEGER:
1074
			case CTF_K_FLOAT:
1075
			case CTF_K_TYPEDEF:
1076
				ctf_decl_sprintf(&cd, "%s", name);
1077
				break;
1078
			case CTF_K_POINTER:
1079
				ctf_decl_sprintf(&cd, "*");
1080
				break;
1081
			case CTF_K_ARRAY:
1082
				ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
1083
				break;
1084
			case CTF_K_FUNCTION:
1085
				ctf_decl_sprintf(&cd, "()");
1086
				break;
1087
			case CTF_K_STRUCT:
1088
			case CTF_K_FORWARD:
1089
				ctf_decl_sprintf(&cd, "struct %s", name);
1090
				break;
1091
			case CTF_K_UNION:
1092
				ctf_decl_sprintf(&cd, "union %s", name);
1093
				break;
1094
			case CTF_K_ENUM:
1095
				ctf_decl_sprintf(&cd, "enum %s", name);
1096
				break;
1097
			case CTF_K_VOLATILE:
1098
				ctf_decl_sprintf(&cd, "volatile");
1099
				break;
1100
			case CTF_K_CONST:
1101
				ctf_decl_sprintf(&cd, "const");
1102
				break;
1103
			case CTF_K_RESTRICT:
1104
				ctf_decl_sprintf(&cd, "restrict");
1105
				break;
1106
			}
1107
1108
			k = cdp->cd_kind;
1109
		}
1110
1111
		if (rp == prec)
1112
			ctf_decl_sprintf(&cd, ")");
1113
	}
1114
1115
	ctf_decl_fini(&cd);
1116
	return (cd.cd_len);
1117
}
1118
1119
static void
1120
fbt_getargdesc(void *arg __unused, dtrace_id_t id __unused, void *parg, dtrace_argdesc_t *desc)
1121
{
1122
	const ushort_t *dp;
1123
	fbt_probe_t *fbt = parg;
1124
	linker_ctf_t lc;
1125
	modctl_t *ctl = fbt->fbtp_ctl;
1126
	int ndx = desc->dtargd_ndx;
1127
	int symindx = fbt->fbtp_symindx;
1128
	uint32_t *ctfoff;
1129
	uint32_t offset;
1130
	ushort_t info, kind, n;
1131
1132
	if (fbt->fbtp_roffset != 0 && desc->dtargd_ndx == 0) {
1133
		(void) strcpy(desc->dtargd_native, "int");
1134
		return;
1135
	}
1136
1137
	desc->dtargd_ndx = DTRACE_ARGNONE;
1138
1139
	/* Get a pointer to the CTF data and it's length. */
1140
	if (linker_ctf_get(ctl, &lc) != 0)
1141
		/* No CTF data? Something wrong? *shrug* */
1142
		return;
1143
1144
	/* Check if this module hasn't been initialised yet. */
1145
	if (*lc.ctfoffp == NULL) {
1146
		/*
1147
		 * Initialise the CTF object and function symindx to
1148
		 * byte offset array.
1149
		 */
1150
		if (fbt_ctfoff_init(ctl, &lc) != 0)
1151
			return;
1152
1153
		/* Initialise the CTF type to byte offset array. */
1154
		if (fbt_typoff_init(&lc) != 0)
1155
			return;
1156
	}
1157
1158
	ctfoff = *lc.ctfoffp;
1159
1160
	if (ctfoff == NULL || *lc.typoffp == NULL)
1161
		return;
1162
1163
	/* Check if the symbol index is out of range. */
1164
	if (symindx >= lc.nsym)
1165
		return;
1166
1167
	/* Check if the symbol isn't cross-referenced. */
1168
	if ((offset = ctfoff[symindx]) == 0xffffffff)
1169
		return;
1170
1171
	dp = (const ushort_t *)(lc.ctftab + offset + sizeof(ctf_header_t));
1172
1173
	info = *dp++;
1174
	kind = CTF_INFO_KIND(info);
1175
	n = CTF_INFO_VLEN(info);
1176
1177
	if (kind == CTF_K_UNKNOWN && n == 0) {
1178
		printf("%s(%d): Unknown function!\n",__func__,__LINE__);
1179
		return;
1180
	}
1181
1182
	if (kind != CTF_K_FUNCTION) {
1183
		printf("%s(%d): Expected a function!\n",__func__,__LINE__);
1184
		return;
1185
	}
1186
1187
	if (fbt->fbtp_roffset != 0) {
1188
		/* Only return type is available for args[1] in return probe. */
1189
		if (ndx > 1)
1190
			return;
1191
		ASSERT(ndx == 1);
1192
	} else {
1193
		/* Check if the requested argument doesn't exist. */
1194
		if (ndx >= n)
1195
			return;
1196
1197
		/* Skip the return type and arguments up to the one requested. */
1198
		dp += ndx + 1;
1199
	}
1200
1201
	if (fbt_type_name(&lc, *dp, desc->dtargd_native, sizeof(desc->dtargd_native)) > 0)
1202
		desc->dtargd_ndx = ndx;
1203
1204
	return;
1205
}
1206
1207
static int
1208
fbt_linker_file_cb(linker_file_t lf, void *arg)
1209
{
1210
1211
	fbt_provide_module(arg, lf);
1212
1213
	return (0);
1214
}
1215
1216
static void
1217
fbt_load(void *dummy)
1218
{
1219
	/* Create the /dev/dtrace/fbt entry. */
1220
	fbt_cdev = make_dev(&fbt_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
1221
	    "dtrace/fbt");
1222
1223
	/* Default the probe table size if not specified. */
1224
	if (fbt_probetab_size == 0)
1225
		fbt_probetab_size = FBT_PROBETAB_SIZE;
1226
1227
	/* Choose the hash mask for the probe table. */
1228
	fbt_probetab_mask = fbt_probetab_size - 1;
1229
1230
	/* Allocate memory for the probe table. */
1231
	fbt_probetab =
1232
	    malloc(fbt_probetab_size * sizeof (fbt_probe_t *), M_FBT, M_WAITOK | M_ZERO);
1233
1234
	dtrace_invop_add(fbt_invop);
1235
1236
	if (dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_USER,
1237
	    NULL, &fbt_pops, NULL, &fbt_id) != 0)
1238
		return;
1239
1240
	/* Create probes for the kernel and already-loaded modules. */
1241
	linker_file_foreach(fbt_linker_file_cb, NULL);
1242
}
1243
1244
1245
static int
1246
fbt_unload()
1247
{
1248
	int error = 0;
1249
1250
	/* De-register the invalid opcode handler. */
1251
	dtrace_invop_remove(fbt_invop);
1252
1253
	/* De-register this DTrace provider. */
1254
	if ((error = dtrace_unregister(fbt_id)) != 0)
1255
		return (error);
1256
1257
	/* Free the probe table. */
1258
	free(fbt_probetab, M_FBT);
1259
	fbt_probetab = NULL;
1260
	fbt_probetab_mask = 0;
1261
1262
	destroy_dev(fbt_cdev);
1263
1264
	return (error);
1265
}
1266
1267
static int
1268
fbt_modevent(module_t mod __unused, int type, void *data __unused)
1269
{
1270
	int error = 0;
1271
1272
	switch (type) {
1273
	case MOD_LOAD:
1274
		break;
1275
1276
	case MOD_UNLOAD:
1277
		break;
1278
1279
	case MOD_SHUTDOWN:
1280
		break;
1281
1282
	default:
1283
		error = EOPNOTSUPP;
1284
		break;
1285
1286
	}
1287
1288
	return (error);
1289
}
1290
1291
static int
1292
fbt_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused, struct thread *td __unused)
1293
{
1294
	return (0);
1295
}
1296
1297
SYSINIT(fbt_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_load, NULL);
1298
SYSUNINIT(fbt_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_unload, NULL);
1299
1300
DEV_MODULE(fbt, fbt_modevent, NULL);
1301
MODULE_VERSION(fbt, 1);
1302
MODULE_DEPEND(fbt, dtrace, 1, 1, 1);
1303
MODULE_DEPEND(fbt, opensolaris, 1, 1, 1);
(-)b/sys/cddl/dev/lockstat/lockstat.c (-1 / +2 lines)
Lines 46-52 Link Here
46
#include <sys/lockstat.h>
46
#include <sys/lockstat.h>
47
47
48
#if defined(__i386__) || defined(__amd64__) || \
48
#if defined(__i386__) || defined(__amd64__) || \
49
	defined(__mips__) || defined(__powerpc__)
49
	defined(__mips__) || defined(__powerpc__) || \
50
	defined(__arm__)
50
#define LOCKSTAT_AFRAMES 1
51
#define LOCKSTAT_AFRAMES 1
51
#else
52
#else
52
#error "architecture not supported"
53
#error "architecture not supported"
(-)b/sys/cddl/dev/profile/profile.c (+10 lines)
Lines 126-131 Link Here
126
#define	PROF_ARTIFICIAL_FRAMES	3
126
#define	PROF_ARTIFICIAL_FRAMES	3
127
#endif
127
#endif
128
128
129
#ifdef __mips
130
/* bogus */
131
#define	PROF_ARTIFICIAL_FRAMES	3
132
#endif
133
134
#ifdef __arm__
135
/* bogus */
136
#define	PROF_ARTIFICIAL_FRAMES	3
137
#endif
138
129
typedef struct profile_probe {
139
typedef struct profile_probe {
130
	char		prof_name[PROF_NAMELEN];
140
	char		prof_name[PROF_NAMELEN];
131
	dtrace_id_t	prof_id;
141
	dtrace_id_t	prof_id;
(-)b/sys/modules/dtrace/Makefile (-1 / +3 lines)
Lines 24-28 SUBDIR+= fbt fasttrap Link Here
24
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_ARCH} == "powerpc64"
24
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_ARCH} == "powerpc64"
25
SUBDIR+=	systrace_freebsd32
25
SUBDIR+=	systrace_freebsd32
26
.endif
26
.endif
27
27
.if ${MACHINE_CPUARCH} == "arm"
28
SUBDIR+=        fbt
29
.endif
28
.include <bsd.subdir.mk>
30
.include <bsd.subdir.mk>
(-)b/sys/modules/dtrace/dtrace/Makefile (-1 / +1 lines)
Lines 22-28 CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/uts/intel Link Here
22
SRCS+=		bus_if.h device_if.h vnode_if.h
22
SRCS+=		bus_if.h device_if.h vnode_if.h
23
23
24
# Needed for dtrace_asm.S
24
# Needed for dtrace_asm.S
25
SRCS+=		assym.s
25
#SRCS+=		assym.s
26
26
27
# These are needed for assym.s
27
# These are needed for assym.s
28
SRCS+=		opt_compat.h opt_kstack_pages.h opt_nfs.h opt_hwpmc_hooks.h
28
SRCS+=		opt_compat.h opt_kstack_pages.h opt_nfs.h opt_hwpmc_hooks.h
(-)b/sys/modules/dtrace/fbt/Makefile (-2 / +2 lines)
Lines 3-10 Link Here
3
.PATH: ${.CURDIR}/../../../cddl/dev/fbt
3
.PATH: ${.CURDIR}/../../../cddl/dev/fbt
4
4
5
KMOD=		fbt
5
KMOD=		fbt
6
.if ${MACHINE_CPUARCH} == "powerpc"
6
.if ${MACHINE_CPUARCH} == "powerpc" || ${MACHINE_CPUARCH} == "arm"
7
SRCS=		fbt_powerpc.c
7
SRCS=		fbt_${MACHINE_CPUARCH}.c
8
.else
8
.else
9
SRCS=		fbt.c
9
SRCS=		fbt.c
10
.endif
10
.endif

Return to bug 192516