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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * tnf driver - provides probe control and kernel trace buffer access
29 * to the user programs prex and tnfxtract.
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/sysmacros.h>
36 #include <sys/cmn_err.h>
37 #include <sys/fcntl.h>
42 #include <sys/errno.h>
46 #include <sys/sunddi.h>
47 #include <sys/modctl.h>
49 #include <sys/debug.h>
50 #include <sys/devops.h>
52 #include <vm/seg_kp.h>
53 #include <sys/tnf_probe.h>
57 #include "tnf_types.h"
58 #include "tnf_trace.h"
63 * Each probe is independently put in the kernel, prex uses
64 * __tnf_probe_list_head and __tnf_tag_list_head as pointers to linked list
65 * for probes and static tnf_tag_data_t, respectively.
66 * tnf used the elf relocation record to build a separate linked list for
67 * the probes and tnf_tag_data_t. We will describe how the linked list for
68 * __tnf_tag_list_head is made, the probe list is very similar.
69 * During the dynamic relocation(in uts/sparc/krtld/kobj_reloc.c),
70 * the &__tnf_tag_version_1(the first member in tnf_tag_data_t data struct)
71 * (and since it is a global variable which was never defined) will be filled
72 * with 0. The following code in kobj_reloc.c will get the address of current
73 * __tnf_tag_list_head and put it in value_p:
74 * #define TAG_MARKER_SYMBOL "__tnf_tag_version_1"
75 * if (strcmp(symname, TAG_MARKER_SYMBOL) == 0) {
77 * *value_p = (Addr) __tnf_tag_list_head; (value_p points to list head)
78 * __tnf_tag_list_head = (void *)*offset_p;(list head is the next record)
82 * the function do_reloc(in the kobj_reloc.c) will put vlaue_p into
83 * &__tnf_tag_version_1
84 * Now the &__tnf_tag_version_1 points to the last list head
85 * and __tnf_tag_list_head points to the new list head.
86 * This is equivalent to attatch a node at the beginning of the list.
89 extern tnf_probe_control_t
*__tnf_probe_list_head
;
90 extern tnf_tag_data_t
*__tnf_tag_list_head
;
91 extern int tnf_changed_probe_list
;
93 static int tnf_attach(dev_info_t
*, ddi_attach_cmd_t
);
94 static int tnf_detach(dev_info_t
*, ddi_detach_cmd_t
);
95 static int tnf_info(dev_info_t
*, ddi_info_cmd_t
, void *, void **);
96 static int tnf_open(dev_t
*, int, int, struct cred
*);
97 static int tnf_close(dev_t
, int, int, struct cred
*);
99 static int tnf_mmap(dev_t
, off_t
, int);
101 static int tnf_ioctl(dev_t
, int, intptr_t, int, struct cred
*, int *);
103 static int tnf_prop_op(dev_t
, dev_info_t
*, ddi_prop_op_t
,
104 int, char *, caddr_t
, int *);
106 static dev_info_t
*tnf_devi
;
110 boolean_t tnf_pidfilter_mode
;
111 boolean_t ctldev_is_open
;
112 int mapdev_open_count
;
114 } tnf_drv_state
= { 0, B_FALSE
, B_FALSE
, 0 };
116 static int tnf_getmaxprobe(caddr_t
, int);
117 static int tnf_getprobevals(caddr_t
, int);
118 static int tnf_getprobestring(caddr_t
, int);
119 static int tnf_setprobevals(caddr_t
, int);
120 static int tnf_getstate(caddr_t
, int);
121 static int tnf_allocbuf(intptr_t);
122 static int tnf_deallocbuf(void);
123 static int tnf_settracing(int);
124 static int tnf_pidfilterset(int);
125 static int tnf_pidfilterget(caddr_t
, int);
126 static int tnf_getpidstate(caddr_t
, int);
127 static int tnf_setpidstate(int, pid_t
, int);
128 static int tnf_getheader(caddr_t
, int);
129 static int tnf_getblock(caddr_t
, int);
130 static int tnf_getfwzone(caddr_t
, int);
132 static void *tnf_test_1(void *, tnf_probe_control_t
*, tnf_probe_setup_t
*);
133 static void *tnf_test_2(void *, tnf_probe_control_t
*, tnf_probe_setup_t
*);
135 #define TNFCTL_MINOR 0
136 #define TNFMAP_MINOR 1
138 struct cb_ops tnf_cb_ops
= {
140 tnf_close
, /* close */
141 nodev
, /* strategy */
146 tnf_ioctl
, /* ioctl */
151 ddi_prop_op
, /* prop_op */
153 D_NEW
| D_MP
/* Driver compatibility flag */
156 struct dev_ops tnf_ops
= {
157 DEVO_REV
, /* devo_rev, */
160 nulldev
, /* identify */
162 tnf_attach
, /* attach */
163 tnf_detach
, /* detach */
165 &tnf_cb_ops
, /* driver operations */
166 (struct bus_ops
*)0, /* no bus operations */
168 ddi_quiesce_not_needed
, /* quiesce */
171 extern struct mod_ops mod_driverops
;
173 static struct modldrv modldrv
= {
175 "kernel probes driver",
179 static struct modlinkage modlinkage
= {
190 mutex_init(&tnf_drv_state
.tnf_mtx
, NULL
, MUTEX_DEFAULT
, NULL
);
192 if ((error
= mod_install(&modlinkage
)) != 0) {
193 mutex_destroy(&tnf_drv_state
.tnf_mtx
);
199 t0
.t_tnf_tpdp
= kmem_zalloc(sizeof (tnf_ops_t
), KM_SLEEP
);
200 /* Initialize tag system */
202 tnf_tag_trace_init();
203 tnf_changed_probe_list
= 1;
210 /* Not safe to unload this module, currently */
215 _info(struct modinfo
*modinfop
)
217 return (mod_info(&modlinkage
, modinfop
));
222 tnf_info(dev_info_t
*dip
, ddi_info_cmd_t infocmd
, void *arg
, void **result
)
227 case DDI_INFO_DEVT2DEVINFO
:
228 *result
= (void *)tnf_devi
;
231 case DDI_INFO_DEVT2INSTANCE
:
242 tnf_attach(dev_info_t
*devi
, ddi_attach_cmd_t cmd
)
244 if (cmd
!= DDI_ATTACH
)
245 return (DDI_FAILURE
);
246 if ((ddi_create_minor_node(devi
, "tnfctl", S_IFCHR
, TNFCTL_MINOR
,
247 DDI_PSEUDO
, NULL
) == DDI_FAILURE
) ||
248 (ddi_create_minor_node(devi
, "tnfmap", S_IFCHR
, TNFMAP_MINOR
,
249 DDI_PSEUDO
, NULL
) == DDI_FAILURE
)) {
250 ddi_remove_minor_node(devi
, NULL
);
251 return (DDI_FAILURE
);
254 return (DDI_SUCCESS
);
258 tnf_detach(dev_info_t
*devi
, ddi_detach_cmd_t cmd
)
260 if (cmd
!= DDI_DETACH
)
261 return (DDI_FAILURE
);
262 ddi_remove_minor_node(devi
, NULL
);
263 return (DDI_SUCCESS
);
267 * property operations. Return the size of the kernel trace buffer. We
268 * only handle size property requests. Others are passed on.
272 tnf_prop_op(dev_t dev
, dev_info_t
*di
, ddi_prop_op_t prop
,
273 int m
, char *name
, caddr_t valuep
, int *lengthp
)
275 int length
, *retbuf
, size
;
277 if (strcmp(name
, "size") == 0) {
279 /* Don't need tnf_mtx, since mapdev_open_count > 0 */
280 size
= tnf_trace_file_size
;
282 length
= *lengthp
; /* get caller's length */
283 *lengthp
= sizeof (int); /* set caller's length */
288 return (DDI_PROP_SUCCESS
);
290 case PROP_LEN_AND_VAL_ALLOC
:
291 retbuf
= kmem_alloc(sizeof (int),
292 (m
& DDI_PROP_CANSLEEP
) ? KM_SLEEP
: KM_NOSLEEP
);
294 return (DDI_PROP_NO_MEMORY
);
295 *(int **)valuep
= retbuf
; /* set caller's buf */
297 return (DDI_PROP_SUCCESS
);
299 case PROP_LEN_AND_VAL_BUF
:
300 if (length
< sizeof (int))
301 return (DDI_PROP_BUF_TOO_SMALL
);
302 *(int *)valuep
= size
;
303 return (DDI_PROP_SUCCESS
);
306 return (ddi_prop_op(dev
, dip
, prop
, m
, name
, valuep
, lengthp
));
312 tnf_open(dev_t
*devp
, int flag
, int otyp
, struct cred
*cred
)
315 mutex_enter(&tnf_drv_state
.tnf_mtx
);
316 if (getminor(*devp
) == TNFCTL_MINOR
) {
317 if (tnf_drv_state
.ctldev_is_open
)
320 tnf_drv_state
.ctldev_is_open
= B_TRUE
;
321 /* stop autounloading -- XXX temporary */
325 /* ASSERT(getminor(*devp) == TNFMAP_MINOR) */
326 ++tnf_drv_state
.mapdev_open_count
;
328 mutex_exit(&tnf_drv_state
.tnf_mtx
);
334 tnf_close(dev_t dev
, int flag
, int otyp
, struct cred
*cred
)
336 if (getminor(dev
) == TNFCTL_MINOR
) {
338 * Request the reenablement of autounloading
341 tnf_drv_state
.ctldev_is_open
= B_FALSE
;
343 /* ASSERT(getminor(dev) == TNFMAP_MINOR) */
345 * Unconditionally zero the open count since close()
346 * is called when last client closes the device.
348 tnf_drv_state
.mapdev_open_count
= 0;
354 * return the address of the image referenced by dev.
356 * 1191344: aliasing problem on VAC machines. It could be made to
357 * work by ensuring that tnf_buf is allocated on a vac_size boundary.
362 tnf_mmap(dev_t dev
, off_t off
, int prot
)
364 register caddr_t addr
;
365 register caddr_t pg_offset
;
367 if (getminor(dev
) != TNFMAP_MINOR
)
369 if (tnf_buf
== 0 || off
>= tnf_trace_file_size
) {
374 pg_offset
= (caddr_t
)((ulong_t
)addr
+ (ulong_t
)off
);
375 return ((int)hat_getpfnum(kas
.a_hat
, pg_offset
));
381 tnf_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
,
382 cred_t
*credp
, int *rvalp
)
386 if ((mode
& FMODELS
) != FNATIVE
)
389 if (getminor(dev
) != TNFCTL_MINOR
&&
390 cmd
!= TIFIOCGSTATE
&&
391 cmd
!= TIFIOCGHEADER
&&
392 cmd
!= TIFIOCGBLOCK
&&
393 cmd
!= TIFIOCGFWZONE
)
397 case TIFIOCGMAXPROBE
:
398 return (tnf_getmaxprobe((caddr_t
)arg
, mode
));
399 case TIFIOCGPROBEVALS
:
400 return (tnf_getprobevals((caddr_t
)arg
, mode
));
401 case TIFIOCGPROBESTRING
:
402 return (tnf_getprobestring((caddr_t
)arg
, mode
));
403 case TIFIOCSPROBEVALS
:
404 return (tnf_setprobevals((caddr_t
)arg
, mode
));
406 return (tnf_getstate((caddr_t
)arg
, mode
));
408 return (tnf_allocbuf(arg
));
409 case TIFIOCDEALLOCBUF
:
410 return (tnf_deallocbuf());
412 /* LINTED cast from 64-bit integer to 32-bit integer */
413 return (tnf_settracing((int)arg
));
414 case TIFIOCSPIDFILTER
:
415 /* LINTED cast from 64-bit integer to 32-bit integer */
416 return (tnf_pidfilterset((int)arg
));
417 case TIFIOCGPIDSTATE
:
418 return (tnf_getpidstate((caddr_t
)arg
, mode
));
423 /* LINTED cast from 64-bit integer to 32-bit integer */
424 return (tnf_setpidstate(filterval
, (pid_t
)arg
, mode
));
425 case TIFIOCPIDFILTERGET
:
426 return (tnf_pidfilterget((caddr_t
)arg
, mode
));
428 return (tnf_getheader((caddr_t
)arg
, mode
));
430 return (tnf_getblock((caddr_t
)arg
, mode
));
432 return (tnf_getfwzone((caddr_t
)arg
, mode
));
443 tnf_getmaxprobe(caddr_t arg
, int mode
)
445 tnf_probe_control_t
*p
;
447 * XXX Still not right for module unload -- just counting
448 * the probes is not enough
450 if (tnf_changed_probe_list
) {
451 mutex_enter(&mod_lock
);
452 tnf_changed_probe_list
= 0;
453 tnf_drv_state
.tnf_probe_count
= 0;
454 for (p
= (tnf_probe_control_t
*)__tnf_probe_list_head
;
456 ++tnf_drv_state
.tnf_probe_count
;
457 mutex_exit(&mod_lock
);
459 if (ddi_copyout((caddr_t
)&tnf_drv_state
.tnf_probe_count
,
460 arg
, sizeof (tnf_drv_state
.tnf_probe_count
), mode
))
466 tnf_getprobevals(caddr_t arg
, int mode
)
468 tnf_probevals_t probebuf
;
469 tnf_probe_control_t
*p
;
472 if (ddi_copyin(arg
, (caddr_t
)&probebuf
, sizeof (probebuf
), mode
))
475 mutex_enter(&mod_lock
);
476 for (i
= 1, p
= (tnf_probe_control_t
*)__tnf_probe_list_head
;
477 p
!= NULL
&& i
!= probebuf
.probenum
;
483 probebuf
.enabled
= (p
->test_func
!= NULL
);
484 probebuf
.traced
= (p
->probe_func
== tnf_trace_commit
);
485 /* LINTED assignment of 64-bit integer to 32-bit integer */
486 probebuf
.attrsize
= strlen(p
->attrs
) + 1;
487 if (ddi_copyout((caddr_t
)&probebuf
,
488 arg
, sizeof (probebuf
), mode
))
491 mutex_exit(&mod_lock
);
496 tnf_getprobestring(caddr_t arg
, int mode
)
498 tnf_probevals_t probebuf
;
499 tnf_probe_control_t
*p
;
502 if (ddi_copyin(arg
, (caddr_t
)&probebuf
, sizeof (probebuf
), mode
))
505 mutex_enter(&mod_lock
);
506 for (i
= 1, p
= (tnf_probe_control_t
*)__tnf_probe_list_head
;
507 p
!= NULL
&& i
!= probebuf
.probenum
;
512 else if (ddi_copyout((caddr_t
)p
->attrs
,
513 arg
, strlen(p
->attrs
) + 1, mode
))
515 mutex_exit(&mod_lock
);
520 tnf_setprobevals(caddr_t arg
, int mode
)
522 tnf_probevals_t probebuf
;
523 tnf_probe_control_t
*p
;
526 if (ddi_copyin(arg
, (caddr_t
)&probebuf
, sizeof (probebuf
), mode
))
529 mutex_enter(&mod_lock
);
530 for (i
= 1, p
= (tnf_probe_control_t
*)__tnf_probe_list_head
;
531 p
!= NULL
&& i
!= probebuf
.probenum
;
538 * First do trace, then enable.
539 * Set test_func last.
542 p
->probe_func
= tnf_trace_commit
;
544 p
->probe_func
= tnf_trace_rollback
;
545 if (probebuf
.enabled
) {
546 p
->alloc_func
= tnf_trace_alloc
;
547 /* this must be set last */
548 if (tnf_drv_state
.tnf_pidfilter_mode
)
549 p
->test_func
= tnf_test_2
;
551 p
->test_func
= tnf_test_1
;
555 mutex_exit(&mod_lock
);
560 tnf_getstate(caddr_t arg
, int mode
)
562 tifiocstate_t tstate
;
565 if (tnf_buf
== NULL
) {
566 tstate
.buffer_state
= TIFIOCBUF_NONE
;
567 tstate
.buffer_size
= 0;
569 switch (tnfw_b_state
& ~TNFW_B_STOPPED
) {
571 tstate
.buffer_state
= TIFIOCBUF_OK
;
573 case TNFW_B_NOBUFFER
:
574 tstate
.buffer_state
= TIFIOCBUF_UNINIT
;
577 tstate
.buffer_state
= TIFIOCBUF_BROKEN
;
580 /* LINTED assignment of 64-bit integer to 32-bit integer */
581 tstate
.buffer_size
= tnf_trace_file_size
;
583 tstate
.trace_stopped
= tnfw_b_state
& TNFW_B_STOPPED
;
584 tstate
.pidfilter_mode
= tnf_drv_state
.tnf_pidfilter_mode
;
585 tstate
.pidfilter_size
= 0;
587 mutex_enter(&pidlock
);
588 for (procp
= practive
; procp
!= NULL
; procp
= procp
->p_next
)
589 if (PROC_IS_FILTER(procp
))
590 tstate
.pidfilter_size
++;
591 mutex_exit(&pidlock
);
593 if (ddi_copyout((caddr_t
)&tstate
, arg
, sizeof (tstate
), mode
))
599 tnf_allocbuf(intptr_t arg
)
606 bufsz
= roundup((size_t)arg
, PAGESIZE
);
609 * XXX Take kernel VM into consideration as well
611 /* bug fix #4057599 if (bufsz > (physmem << PAGESHIFT) / 2) */
612 if (btop(bufsz
) > (physmem
/ 2))
614 if (bufsz
< TNF_TRACE_FILE_MIN
)
615 bufsz
= TNF_TRACE_FILE_MIN
;
618 tnf_buf
= kmem_zalloc(bufsz
, KM_SLEEP
);
620 /* LINTED cast from 64-bit integer to 32-bit intege */
621 tnf_buf
= segkp_get(segkp
, (int)bufsz
,
622 KPD_ZERO
| KPD_LOCKED
| KPD_NO_ANON
);
627 tnf_trace_file_size
= bufsz
;
633 * Process a "deallocate buffer" ioctl request. Tracing must be turned
634 * off. We must clear references to the buffer from the tag sites;
635 * invalidate all threads' notions of block ownership; make sure nobody
636 * is executing a probe (they might have started before tracing was
637 * turned off); and free the buffer.
644 tnf_probe_control_t
*probep
;
645 tnf_tag_data_t
*tagp
;
647 if (tnf_drv_state
.mapdev_open_count
> 0 || tnf_tracing_active
)
653 * Make sure nobody is executing a probe.
654 * (They could be if they got started while
655 * tnf_tracing_active was still on.) Grab
656 * pidlock, and check the busy flag in all
659 mutex_enter(&pidlock
);
662 if (t
->t_tnf_tpdp
!= NULL
) {
663 /* LINTED pointer cast may result in improper alignment */
664 tpdp
= (tnf_ops_t
*)t
->t_tnf_tpdp
;
665 if (LOCK_HELD(&tpdp
->busy
)) {
666 mutex_exit(&pidlock
);
669 tpdp
->wcb
.tnfw_w_pos
.tnfw_w_block
= NULL
;
670 tpdp
->wcb
.tnfw_w_tag_pos
.tnfw_w_block
= NULL
;
671 tpdp
->schedule
.record_p
= NULL
;
674 } while (t
!= curthread
);
675 mutex_exit(&pidlock
);
678 * Zap all references to the buffer we're freeing.
679 * Grab mod_lock while walking list to keep it
682 mutex_enter(&mod_lock
);
683 tagp
= (tnf_tag_data_t
*)__tnf_tag_list_head
;
684 while (tagp
!= NULL
) {
686 tagp
= (tnf_tag_data_t
*)tagp
->tag_version
;
688 probep
= (tnf_probe_control_t
*)__tnf_probe_list_head
;
689 while (probep
!= NULL
) {
691 probep
= probep
->next
;
693 mutex_exit(&mod_lock
);
695 tnfw_b_state
= TNFW_B_NOBUFFER
| TNFW_B_STOPPED
;
697 kmem_free(tnf_buf
, tnf_trace_file_size
);
699 segkp_release(segkp
, tnf_buf
);
707 tnf_settracing(int arg
)
717 #ifdef _TNF_SPEED_TEST
722 for (i
= 0; i
< NITER
; i
++)
723 TNF_PROBE_0(tnf_speed_0
, "tnf", /* CSTYLED */);
724 for (i
= 0; i
< NITER
; i
++)
725 TNF_PROBE_1(tnf_speed_1
, "tnf", /* CSTYLED */,
727 for (i
= 0; i
< NITER
; i
++)
728 TNF_PROBE_2(tnf_speed_2
, "tnf", /* CSTYLED */,
732 #endif /* _TNF_SPEED_TEST */
738 tnf_getpidstate(caddr_t arg
, int mode
)
745 if (ddi_copyin(arg
, (caddr_t
)&pid
, sizeof (pid
), mode
))
748 mutex_enter(&pidlock
);
749 if ((procp
= prfind(pid
)) != NULL
)
750 result
= PROC_IS_FILTER(procp
);
753 mutex_exit(&pidlock
);
756 if (ddi_copyout((caddr_t
)&result
, (caddr_t
)arg
,
757 sizeof (result
), mode
))
764 tnf_setpidstate(int filterval
, pid_t pid
, int mode
)
769 mutex_enter(&pidlock
);
770 if ((procp
= prfind(pid
)) != NULL
)
772 PROC_FILTER_SET(procp
);
774 PROC_FILTER_CLR(procp
);
777 mutex_exit(&pidlock
);
783 tnf_pidfilterset(int mode
)
785 tnf_probe_control_t
*p
;
786 tnf_probe_test_func_t func
;
788 tnf_drv_state
.tnf_pidfilter_mode
= mode
;
790 /* Establish correct test func for each probe */
796 mutex_enter(&mod_lock
);
797 p
= (tnf_probe_control_t
*)__tnf_probe_list_head
;
799 if (p
->test_func
!= NULL
)
803 mutex_exit(&mod_lock
);
809 tnf_pidfilterget(caddr_t dest
, int mode
)
814 pid_t
*filterbuf
, *bufp
;
817 /* Count how many processes in filter set (upper bound) */
818 mutex_enter(&pidlock
);
819 for (procp
= practive
; procp
!= NULL
; procp
= procp
->p_next
)
820 if (PROC_IS_FILTER(procp
))
822 mutex_exit(&pidlock
);
824 /* Allocate temp space to hold filter set (upper bound) */
825 sz
= sizeof (pid_t
) * (filtercount
+ 1);
826 filterbuf
= kmem_zalloc(sz
, KM_SLEEP
);
829 * NOTE: The filter set cannot grow between the first and
830 * second acquisitions of pidlock. This is currently true
832 * 1. /dev/tnfctl is exclusive open, so all driver
833 * control operations, including changing the filter
834 * set and this code, are effectively single-threaded.
835 * 2. There is no in-kernel API to manipulate the filter
836 * set (i.e. toggle the on/off bit in a proc struct).
837 * 3. The proc filter bit is not inherited across a fork()
838 * operation; the child starts with the bit off.
839 * If any of these assumptions is invalidated, a possible
840 * solution is to check whether we're overflowing the allocated
841 * filterbuf below, and back out and restart from the beginning
844 * The code below handles the case when the filter set shrinks
845 * due to processes exiting.
848 /* Fill in filter set */
849 bufp
= filterbuf
+ 1; /* first word is for count */
850 filtercount
= 0; /* recomputed below */
851 mutex_enter(&pidlock
);
852 for (procp
= practive
; procp
!= NULL
; procp
= procp
->p_next
) {
853 if (PROC_IS_FILTER(procp
)) {
855 *bufp
++ = procp
->p_pid
;
858 mutex_exit(&pidlock
);
860 /* Set filtercount */
861 *filterbuf
= (pid_t
)filtercount
;
863 /* Copy out result */
864 if (ddi_copyout((caddr_t
)filterbuf
, dest
, sz
, mode
))
867 /* Free temp space */
868 kmem_free(filterbuf
, sz
);
874 tnf_getheader(caddr_t arg
, int mode
)
878 if (ddi_copyout(tnf_buf
, arg
, TNF_BLOCK_SIZE
, mode
))
884 tnf_getblock(caddr_t arg
, int mode
)
887 tifiocgblock_t parms
;
889 tnf_block_header_t
*blk
;
893 if (ddi_copyin(arg
, (caddr_t
)&parms
, sizeof (parms
), mode
))
895 area
= tnf_buf
+ TNF_DIRECTORY_SIZE
+
896 parms
.block_num
* TNF_BLOCK_SIZE
;
897 if (area
< tnf_buf
+ TNF_DIRECTORY_SIZE
||
898 area
>= tnf_buf
+ tnf_trace_file_size
)
900 /* LINTED pointer cast */
901 blk
= (tnf_block_header_t
*)area
;
903 * B-lock the block while we're reading
905 if (!lock_try(&blk
->B_lock
))
907 if (ddi_copyout(area
, parms
.dst_addr
, TNF_BLOCK_SIZE
, mode
))
909 lock_clear(&blk
->B_lock
);
914 tnf_getfwzone(caddr_t arg
, int mode
)
920 if (ddi_copyin(arg
, (caddr_t
)&parms
, sizeof (parms
), mode
))
922 if (ddi_copyout(tnf_buf
+ TNF_BLOCK_SIZE
+ parms
.start
*
923 sizeof (tnf_ref32_t
), (caddr_t
)parms
.dst_addr
,
924 parms
.slots
* (int)(sizeof (tnf_ref32_t
)), mode
))
931 tnf_test_1(void *tpdp
, tnf_probe_control_t
*probe_p
, tnf_probe_setup_t
*sp
)
933 tpdp
= (void *)curthread
->t_tnf_tpdp
;
935 return (tnf_trace_alloc((tnf_ops_t
*)tpdp
, probe_p
, sp
));
941 tnf_test_2(void *tpdp
, tnf_probe_control_t
*probe_p
, tnf_probe_setup_t
*sp
)
943 tpdp
= (void *)curthread
->t_tnf_tpdp
;
944 if (tpdp
!= NULL
&& PROC_IS_FILTER(curproc
))
945 return (tnf_trace_alloc((tnf_ops_t
*)tpdp
, probe_p
, sp
));