FreeBSD/Linux Kernel Cross Reference
sys/kern/sys_pmc.c
1 /* $NetBSD: sys_pmc.c,v 1.6 2006/11/01 10:17:59 yamt Exp $ */
2
3 /*
4 * Copyright (c) 2002 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Allen Briggs for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include "opt_perfctrs.h"
39
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: sys_pmc.c,v 1.6 2006/11/01 10:17:59 yamt Exp $");
42
43 #include <sys/param.h>
44 #include <sys/proc.h>
45 #include <sys/mount.h>
46 #include <sys/systm.h>
47 #include <sys/sa.h>
48 #include <sys/syscallargs.h>
49 #include <sys/types.h>
50
51 #if defined(PERFCTRS)
52 #include <sys/pmc.h>
53 #endif
54
55 /*
56 * XXX We need a multiprocessor locking protocol!
57 */
58
59 int
60 sys_pmc_control(struct lwp *l, void *v, register_t *rv)
61 {
62 #ifndef PERFCTRS
63 return ENXIO;
64 #else
65 struct sys_pmc_control_args /* {
66 syscallarg(int) ctr;
67 syscallarg(int) op;
68 syscallarg(void *) args;
69 } */ *uap = v;
70 struct pmc_counter_cfg cfg;
71 void *args;
72 int ctr, operation, error=0;
73
74 ctr = SCARG(uap, ctr);
75 operation = SCARG(uap, op);
76
77 switch (operation) {
78 case PMC_OP_START:
79 if (!pmc_counter_isconfigured(l->l_proc, ctr)) {
80 return ENXIO;
81 }
82 if (pmc_counter_isrunning(l->l_proc, ctr)) {
83 return EINPROGRESS;
84 }
85 pmc_enable_counter(l->l_proc, ctr);
86 break;
87 case PMC_OP_STOP:
88 if (!pmc_counter_isconfigured(l->l_proc, ctr)) {
89 return ENXIO;
90 }
91 if (!pmc_counter_isrunning(l->l_proc, ctr)) {
92 /* Nothing to do */
93 return 0;
94 }
95 pmc_disable_counter(l->l_proc, ctr);
96 break;
97 case PMC_OP_CONFIGURE:
98 args = SCARG(uap, args);
99
100 if (pmc_counter_isrunning(l->l_proc, ctr)) {
101 pmc_disable_counter(l->l_proc, ctr);
102 }
103 error = copyin(args, &cfg, sizeof(struct pmc_counter_cfg));
104 if (error == 0) {
105 error = pmc_configure_counter(l->l_proc, ctr, &cfg);
106 }
107 break;
108 case PMC_OP_PROFSTART:
109 args = SCARG(uap, args);
110
111 error = copyin(args, &cfg, sizeof(struct pmc_counter_cfg));
112 if (error == 0) {
113 error = pmc_start_profiling(ctr, &cfg);
114 }
115 break;
116 case PMC_OP_PROFSTOP:
117 error = pmc_stop_profiling(ctr);
118 break;
119 default:
120 error = EINVAL;
121 break;
122 }
123 return error;
124 #endif
125 }
126
127 int
128 sys_pmc_get_info(struct lwp *l, void *v, register_t *rv)
129 {
130 #ifndef PERFCTRS
131 return ENXIO;
132 #else
133 struct sys_pmc_get_info_args /* {
134 syscallarg(int) ctr;
135 syscallarg(int) op;
136 syscallarg(void *) args;
137 } */ *uap = v;
138 uint64_t val;
139 void *args;
140 int nctrs, ctr, ctrt, request, error=0, flags=0;
141
142 ctr = SCARG(uap, ctr);
143 request = SCARG(uap, op);
144 args = SCARG(uap, args);
145
146 nctrs = pmc_get_num_counters();
147
148 switch (request) {
149 case PMC_INFO_NCOUNTERS: /* args should be (int *) */
150 error = copyout(&nctrs, args, sizeof(int));
151 break;
152
153 case PMC_INFO_CPUCTR_TYPE: /* args should be (int *) */
154 ctrt = pmc_get_counter_type(ctr);
155 error = copyout(&ctrt, args, sizeof(int));
156 break;
157 /* args should be (pmc_ctr_t *) */
158 case PMC_INFO_ACCUMULATED_COUNTER_VALUE:
159 flags = PMC_VALUE_FLAGS_CHILDREN;
160 /*FALLTHROUGH*/
161 case PMC_INFO_COUNTER_VALUE:
162 if (ctr < 0 || ctr >= nctrs) {
163 return EINVAL;
164 }
165 error = pmc_get_counter_value(l->l_proc, ctr, flags, &val);
166 if (error == 0) {
167 error = copyout(&val, args, sizeof(uint64_t));
168 }
169 break;
170 default:
171 error = EINVAL;
172 break;
173 }
174 return error;
175 #endif
176 }
Cache object: 5c31f03a038f7ffb41fa0fdb756d47ef
|