xref: /titanic_51/usr/src/uts/common/io/cpc.c (revision 23c352973f956f97f817e65150aad7e1cebeb228)
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 /*
30  * CPU Performance Counter system calls and device driver.
31  *
32  * This module uses a combination of thread context operators, and
33  * thread-specific data to export CPU performance counters
34  * via both a system call and a driver interface.
35  *
36  * There are three access methods exported - the 'shared' device
37  * and the 'private' and 'agent' variants of the system call.
38  *
39  * The shared device treats the performance counter registers as
40  * a processor metric, regardless of the work scheduled on them.
41  * The private system call treats the performance counter registers
42  * as a property of a single lwp.  This is achieved by using the
43  * thread context operators to virtualize the contents of the
44  * performance counter registers between lwps.
45  *
46  * The agent method is like the private method, except that it must
47  * be accessed via /proc's agent lwp to allow the counter context of
48  * other threads to be examined safely.
49  *
50  * The shared usage fundamentally conflicts with the agent and private usage;
51  * almost all of the complexity of the module is needed to allow these two
52  * models to co-exist in a reasonable way.
53  */
54 
55 #include <sys/types.h>
56 #include <sys/file.h>
57 #include <sys/errno.h>
58 #include <sys/open.h>
59 #include <sys/cred.h>
60 #include <sys/conf.h>
61 #include <sys/stat.h>
62 #include <sys/processor.h>
63 #include <sys/cpuvar.h>
64 #include <sys/disp.h>
65 #include <sys/kmem.h>
66 #include <sys/modctl.h>
67 #include <sys/ddi.h>
68 #include <sys/sunddi.h>
69 #include <sys/nvpair.h>
70 #include <sys/policy.h>
71 #include <sys/machsystm.h>
72 #include <sys/cpc_impl.h>
73 #include <sys/cpc_pcbe.h>
74 #include <sys/kcpc.h>
75 
76 static int kcpc_copyin_set(kcpc_set_t **set, void *ubuf, size_t len);
77 static int kcpc_verify_set(kcpc_set_t *set);
78 static uint32_t kcpc_nvlist_npairs(nvlist_t *list);
79 
80 /*
81  * Generic attributes supported regardless of processor.
82  */
83 
84 #define	ATTRLIST "picnum"
85 #define	SEPARATOR ","
86 
87 /*
88  * System call to access CPU performance counters.
89  */
90 static int
91 cpc(int cmd, id_t lwpid, void *udata1, void *udata2, void *udata3)
92 {
93 	kthread_t	*t;
94 	int		error;
95 	int		size;
96 	const char	*str;
97 	int		code;
98 
99 	/*
100 	 * This CPC syscall should only be loaded if it found a PCBE to use.
101 	 */
102 	ASSERT(pcbe_ops != NULL);
103 
104 	if (curproc->p_agenttp == curthread) {
105 		/*
106 		 * Only if /proc is invoking this system call from
107 		 * the agent thread do we allow the caller to examine
108 		 * the contexts of other lwps in the process.  And
109 		 * because we know we're the agent, we know we don't
110 		 * have to grab p_lock because no-one else can change
111 		 * the state of the process.
112 		 */
113 		if ((t = idtot(curproc, lwpid)) == NULL || t == curthread)
114 			return (set_errno(ESRCH));
115 		ASSERT(t->t_tid == lwpid && ttolwp(t) != NULL);
116 	} else
117 		t = curthread;
118 
119 	if (t->t_cpc_set == NULL && (cmd == CPC_SAMPLE || cmd == CPC_RELE))
120 		return (set_errno(EINVAL));
121 
122 	switch (cmd) {
123 	case CPC_BIND:
124 		/*
125 		 * udata1 = pointer to packed nvlist buffer
126 		 * udata2 = size of packed nvlist buffer
127 		 * udata3 = User addr to return error subcode in.
128 		 */
129 
130 		rw_enter(&kcpc_cpuctx_lock, RW_READER);
131 		if (kcpc_cpuctx) {
132 			rw_exit(&kcpc_cpuctx_lock);
133 			return (set_errno(EAGAIN));
134 		}
135 
136 		if (kcpc_hw_lwp_hook() != 0) {
137 			rw_exit(&kcpc_cpuctx_lock);
138 			return (set_errno(EACCES));
139 		}
140 
141 		/*
142 		 * An LWP may only have one set bound to it at a time; if there
143 		 * is a set bound to this LWP already, we unbind it here.
144 		 */
145 		if (t->t_cpc_set != NULL)
146 			(void) kcpc_unbind(t->t_cpc_set);
147 		ASSERT(t->t_cpc_set == NULL);
148 
149 		if ((error = kcpc_copyin_set(&t->t_cpc_set, udata1,
150 		    (size_t)udata2)) != 0) {
151 			rw_exit(&kcpc_cpuctx_lock);
152 			return (set_errno(error));
153 		}
154 
155 		if ((error = kcpc_verify_set(t->t_cpc_set)) != 0) {
156 			rw_exit(&kcpc_cpuctx_lock);
157 			kcpc_free_set(t->t_cpc_set);
158 			t->t_cpc_set = NULL;
159 			if (copyout(&error, udata3, sizeof (error)) == -1)
160 				return (set_errno(EFAULT));
161 			return (set_errno(EINVAL));
162 		}
163 
164 		if ((error = kcpc_bind_thread(t->t_cpc_set, t, &code)) != 0) {
165 			rw_exit(&kcpc_cpuctx_lock);
166 			kcpc_free_set(t->t_cpc_set);
167 			t->t_cpc_set = NULL;
168 			/*
169 			 * EINVAL and EACCES are the only errors with more
170 			 * specific subcodes.
171 			 */
172 			if ((error == EINVAL || error == EACCES) &&
173 			    copyout(&code, udata3, sizeof (code)) == -1)
174 				return (set_errno(EFAULT));
175 			return (set_errno(error));
176 		}
177 
178 		rw_exit(&kcpc_cpuctx_lock);
179 		return (0);
180 	case CPC_SAMPLE:
181 		/*
182 		 * udata1 = pointer to user's buffer
183 		 * udata2 = pointer to user's hrtime
184 		 * udata3 = pointer to user's tick
185 		 */
186 		/*
187 		 * We only allow thread-bound sets to be sampled via the
188 		 * syscall, so if this set has a CPU-bound context, return an
189 		 * error.
190 		 */
191 		if (t->t_cpc_set->ks_ctx->kc_cpuid != -1)
192 			return (set_errno(EINVAL));
193 		if ((error = kcpc_sample(t->t_cpc_set, udata1, udata2,
194 		    udata3)) != 0)
195 			return (set_errno(error));
196 
197 		return (0);
198 	case CPC_PRESET:
199 	case CPC_RESTART:
200 		/*
201 		 * These are valid only if this lwp has a bound set.
202 		 */
203 		if (t->t_cpc_set == NULL)
204 			return (set_errno(EINVAL));
205 		if (cmd == CPC_PRESET) {
206 			/*
207 			 * The preset is shipped up to us from userland in two
208 			 * parts. This lets us handle 64-bit values from 32-bit
209 			 * and 64-bit applications in the same manner.
210 			 *
211 			 * udata1 = index of request to preset
212 			 * udata2 = new 64-bit preset (most sig. 32 bits)
213 			 * udata3 = new 64-bit preset (least sig. 32 bits)
214 			 */
215 			if ((error = kcpc_preset(t->t_cpc_set, (intptr_t)udata1,
216 			    ((uint64_t)(uintptr_t)udata2 << 32ULL) |
217 			    (uint64_t)(uintptr_t)udata3)) != 0)
218 				return (set_errno(error));
219 		} else {
220 			/*
221 			 * udata[1-3] = unused
222 			 */
223 			if ((error = kcpc_restart(t->t_cpc_set)) != 0)
224 				return (set_errno(error));
225 		}
226 		return (0);
227 	case CPC_ENABLE:
228 	case CPC_DISABLE:
229 		udata1 = 0;
230 		/*FALLTHROUGH*/
231 	case CPC_USR_EVENTS:
232 	case CPC_SYS_EVENTS:
233 		if (t != curthread || t->t_cpc_set == NULL)
234 			return (set_errno(EINVAL));
235 		/*
236 		 * Provided for backwards compatibility with CPCv1.
237 		 *
238 		 * Stop the counters and record the current counts. Use the
239 		 * counts as the preset to rebind a new set with the requests
240 		 * reconfigured as requested.
241 		 *
242 		 * udata1: 1 == enable; 0 == disable
243 		 * udata{2,3}: unused
244 		 */
245 		rw_enter(&kcpc_cpuctx_lock, RW_READER);
246 		if ((error = kcpc_enable(t,
247 		    cmd, (int)(uintptr_t)udata1)) != 0) {
248 			rw_exit(&kcpc_cpuctx_lock);
249 			return (set_errno(error));
250 		}
251 		rw_exit(&kcpc_cpuctx_lock);
252 		return (0);
253 	case CPC_NPIC:
254 		return (cpc_ncounters);
255 	case CPC_CAPS:
256 		return (pcbe_ops->pcbe_caps);
257 	case CPC_EVLIST_SIZE:
258 	case CPC_LIST_EVENTS:
259 		/*
260 		 * udata1 = pointer to user's int or buffer
261 		 * udata2 = picnum
262 		 * udata3 = unused
263 		 */
264 		if ((uintptr_t)udata2 >= cpc_ncounters)
265 			return (set_errno(EINVAL));
266 
267 		size = strlen(
268 		    pcbe_ops->pcbe_list_events((uintptr_t)udata2)) + 1;
269 
270 		if (cmd == CPC_EVLIST_SIZE) {
271 			if (suword32(udata1, size) == -1)
272 				return (set_errno(EFAULT));
273 		} else {
274 			if (copyout(
275 			    pcbe_ops->pcbe_list_events((uintptr_t)udata2),
276 			    udata1, size) == -1)
277 				return (set_errno(EFAULT));
278 		}
279 		return (0);
280 	case CPC_ATTRLIST_SIZE:
281 	case CPC_LIST_ATTRS:
282 		/*
283 		 * udata1 = pointer to user's int or buffer
284 		 * udata2 = unused
285 		 * udata3 = unused
286 		 *
287 		 * attrlist size is length of PCBE-supported attributes, plus
288 		 * room for "picnum\0" plus an optional ',' separator char.
289 		 */
290 		str = pcbe_ops->pcbe_list_attrs();
291 		size = strlen(str) + sizeof (SEPARATOR ATTRLIST) + 1;
292 		if (str[0] != '\0')
293 			/*
294 			 * A ',' separator character is necessary.
295 			 */
296 			size += 1;
297 
298 		if (cmd == CPC_ATTRLIST_SIZE) {
299 			if (suword32(udata1, size) == -1)
300 				return (set_errno(EFAULT));
301 		} else {
302 			/*
303 			 * Copyout the PCBE attributes, and then append the
304 			 * generic attribute list (with separator if necessary).
305 			 */
306 			if (copyout(str, udata1, strlen(str)) == -1)
307 				return (set_errno(EFAULT));
308 			if (str[0] != '\0') {
309 				if (copyout(SEPARATOR ATTRLIST,
310 				    ((char *)udata1) + strlen(str),
311 				    strlen(SEPARATOR ATTRLIST) + 1)
312 				    == -1)
313 					return (set_errno(EFAULT));
314 			} else
315 				if (copyout(ATTRLIST,
316 				    (char *)udata1 + strlen(str),
317 				    strlen(ATTRLIST) + 1) == -1)
318 					return (set_errno(EFAULT));
319 		}
320 		return (0);
321 	case CPC_IMPL_NAME:
322 	case CPC_CPUREF:
323 		/*
324 		 * udata1 = pointer to user's buffer
325 		 * udata2 = unused
326 		 * udata3 = unused
327 		 */
328 		if (cmd == CPC_IMPL_NAME) {
329 			str = pcbe_ops->pcbe_impl_name();
330 			ASSERT(strlen(str) < CPC_MAX_IMPL_NAME);
331 		} else {
332 			str = pcbe_ops->pcbe_cpuref();
333 			ASSERT(strlen(str) < CPC_MAX_CPUREF);
334 		}
335 
336 		if (copyout(str, udata1, strlen(str) + 1) != 0)
337 			return (set_errno(EFAULT));
338 		return (0);
339 	case CPC_INVALIDATE:
340 		kcpc_invalidate(t);
341 		return (0);
342 	case CPC_RELE:
343 		if ((error = kcpc_unbind(t->t_cpc_set)) != 0)
344 			return (set_errno(error));
345 		return (0);
346 	default:
347 		return (set_errno(EINVAL));
348 	}
349 }
350 
351 /*
352  * The 'shared' device allows direct access to the
353  * performance counter control register of the current CPU.
354  * The major difference between the contexts created here and those
355  * above is that the context handlers are -not- installed, thus
356  * no context switching behaviour occurs.
357  *
358  * Because they manipulate per-cpu state, these ioctls can
359  * only be invoked from a bound lwp, by a caller with the cpc_cpu privilege
360  * who can open the relevant entry in /devices (the act of holding it open
361  * causes other uses of the counters to be suspended).
362  *
363  * Note that for correct results, the caller -must- ensure that
364  * all existing per-lwp contexts are either inactive or marked invalid;
365  * that's what the open routine does.
366  */
367 /*ARGSUSED*/
368 static int
369 kcpc_ioctl(dev_t dev, int cmd, intptr_t data, int flags, cred_t *cr, int *rvp)
370 {
371 	kthread_t	*t = curthread;
372 	processorid_t	cpuid;
373 	void		*udata1 = NULL;
374 	void		*udata2 = NULL;
375 	void		*udata3 = NULL;
376 	int		error;
377 	int		code;
378 
379 	STRUCT_DECL(__cpc_args, args);
380 
381 	STRUCT_INIT(args, flags);
382 
383 	if (curthread->t_bind_cpu != getminor(dev))
384 		return (EAGAIN);  /* someone unbound it? */
385 
386 	cpuid = getminor(dev);
387 
388 	if (cmd == CPCIO_BIND || cmd == CPCIO_SAMPLE) {
389 		if (copyin((void *)data, STRUCT_BUF(args),
390 		    STRUCT_SIZE(args)) == -1)
391 			return (EFAULT);
392 
393 		udata1 = STRUCT_FGETP(args, udata1);
394 		udata2 = STRUCT_FGETP(args, udata2);
395 		udata3 = STRUCT_FGETP(args, udata3);
396 	}
397 
398 	switch (cmd) {
399 	case CPCIO_BIND:
400 		/*
401 		 * udata1 = pointer to packed nvlist buffer
402 		 * udata2 = size of packed nvlist buffer
403 		 * udata3 = User addr to return error subcode in.
404 		 */
405 		if (t->t_cpc_set != NULL) {
406 			(void) kcpc_unbind(t->t_cpc_set);
407 			ASSERT(t->t_cpc_set == NULL);
408 		}
409 
410 		if ((error = kcpc_copyin_set(&t->t_cpc_set, udata1,
411 		    (size_t)udata2)) != 0) {
412 			return (error);
413 		}
414 
415 		if ((error = kcpc_verify_set(t->t_cpc_set)) != 0) {
416 			kcpc_free_set(t->t_cpc_set);
417 			t->t_cpc_set = NULL;
418 			if (copyout(&error, udata3, sizeof (error)) == -1)
419 				return (EFAULT);
420 			return (EINVAL);
421 		}
422 
423 		if ((error = kcpc_bind_cpu(t->t_cpc_set, cpuid, &code)) != 0) {
424 			kcpc_free_set(t->t_cpc_set);
425 			t->t_cpc_set = NULL;
426 			/*
427 			 * Subcodes are only returned for EINVAL and EACCESS.
428 			 */
429 			if ((error == EINVAL || error == EACCES) &&
430 			    copyout(&code, udata3, sizeof (code)) == -1)
431 				return (EFAULT);
432 			return (error);
433 		}
434 
435 		return (0);
436 	case CPCIO_SAMPLE:
437 		/*
438 		 * udata1 = pointer to user's buffer
439 		 * udata2 = pointer to user's hrtime
440 		 * udata3 = pointer to user's tick
441 		 */
442 		/*
443 		 * Only CPU-bound sets may be sampled via the ioctl(). If this
444 		 * set has no CPU-bound context, return an error.
445 		 */
446 		if (t->t_cpc_set == NULL)
447 			return (EINVAL);
448 		if ((error = kcpc_sample(t->t_cpc_set, udata1, udata2,
449 		    udata3)) != 0)
450 			return (error);
451 		return (0);
452 	case CPCIO_RELE:
453 		if (t->t_cpc_set == NULL)
454 			return (EINVAL);
455 		return (kcpc_unbind(t->t_cpc_set));
456 	default:
457 		return (EINVAL);
458 	}
459 }
460 
461 /*
462  * The device supports multiple opens, but only one open
463  * is allowed per processor.  This is to enable multiple
464  * instances of tools looking at different processors.
465  */
466 #define	KCPC_MINOR_SHARED		((minor_t)0x3fffful)
467 
468 static ulong_t *kcpc_cpumap;		/* bitmap of cpus */
469 
470 /*ARGSUSED1*/
471 static int
472 kcpc_open(dev_t *dev, int flags, int otyp, cred_t *cr)
473 {
474 	processorid_t	cpuid;
475 	int		error;
476 
477 	ASSERT(pcbe_ops != NULL);
478 
479 	if ((error = secpolicy_cpc_cpu(cr)) != 0)
480 		return (error);
481 	if (getminor(*dev) != KCPC_MINOR_SHARED)
482 		return (ENXIO);
483 	if ((cpuid = curthread->t_bind_cpu) == PBIND_NONE)
484 		return (EINVAL);
485 	if (cpuid > max_cpuid)
486 		return (EINVAL);
487 
488 	rw_enter(&kcpc_cpuctx_lock, RW_WRITER);
489 	if (++kcpc_cpuctx == 1) {
490 		ASSERT(kcpc_cpumap == NULL);
491 		kcpc_cpumap = kmem_zalloc(BT_SIZEOFMAP(max_cpuid + 1),
492 		    KM_SLEEP);
493 		/*
494 		 * When this device is open for processor-based contexts,
495 		 * no further lwp-based contexts can be created.
496 		 *
497 		 * Since this is the first open, ensure that all existing
498 		 * contexts are invalidated.
499 		 */
500 		kcpc_invalidate_all();
501 	} else if (BT_TEST(kcpc_cpumap, cpuid)) {
502 		kcpc_cpuctx--;
503 		rw_exit(&kcpc_cpuctx_lock);
504 		return (EAGAIN);
505 	} else if (kcpc_hw_cpu_hook(cpuid, kcpc_cpumap) != 0) {
506 		kcpc_cpuctx--;
507 		rw_exit(&kcpc_cpuctx_lock);
508 		return (EACCES);
509 	}
510 	BT_SET(kcpc_cpumap, cpuid);
511 	rw_exit(&kcpc_cpuctx_lock);
512 
513 	*dev = makedevice(getmajor(*dev), (minor_t)cpuid);
514 
515 	return (0);
516 }
517 
518 /*ARGSUSED1*/
519 static int
520 kcpc_close(dev_t dev, int flags, int otyp, cred_t *cr)
521 {
522 	rw_enter(&kcpc_cpuctx_lock, RW_WRITER);
523 	BT_CLEAR(kcpc_cpumap, getminor(dev));
524 	if (--kcpc_cpuctx == 0) {
525 		kmem_free(kcpc_cpumap, BT_SIZEOFMAP(max_cpuid + 1));
526 		kcpc_cpumap = NULL;
527 	}
528 	ASSERT(kcpc_cpuctx >= 0);
529 	rw_exit(&kcpc_cpuctx_lock);
530 
531 	return (0);
532 }
533 
534 /*
535  * Sane boundaries on the size of packed lists. In bytes.
536  */
537 #define	CPC_MIN_PACKSIZE 4
538 #define	CPC_MAX_PACKSIZE 10000
539 
540 /*
541  * Sane boundary on the number of requests a set can contain.
542  */
543 #define	CPC_MAX_NREQS 100
544 
545 /*
546  * Sane boundary on the number of attributes a request can contain.
547  */
548 #define	CPC_MAX_ATTRS 50
549 
550 /*
551  * Copy in a packed nvlist from the user and create a request set out of it.
552  * If successful, return 0 and store a pointer to the set we've created. Returns
553  * error code on error.
554  */
555 int
556 kcpc_copyin_set(kcpc_set_t **inset, void *ubuf, size_t len)
557 {
558 	kcpc_set_t	*set;
559 	int		i;
560 	int		j;
561 	char		*packbuf;
562 
563 	nvlist_t	*nvl;
564 	nvpair_t	*nvp = NULL;
565 
566 	nvlist_t	*attrs;
567 	nvpair_t	*nvp_attr;
568 	kcpc_attr_t	*attrp;
569 
570 	nvlist_t	**reqlist;
571 	uint_t		nreqs;
572 	uint64_t	uint64;
573 	uint32_t	uint32;
574 	uint32_t	setflags = (uint32_t)-1;
575 	char		*string;
576 	char		*name;
577 
578 	if (len < CPC_MIN_PACKSIZE || len > CPC_MAX_PACKSIZE)
579 		return (EINVAL);
580 
581 	packbuf = kmem_alloc(len, KM_SLEEP);
582 
583 	if (copyin(ubuf, packbuf, len) == -1) {
584 		kmem_free(packbuf, len);
585 		return (EFAULT);
586 	}
587 
588 	if (nvlist_unpack(packbuf, len, &nvl, KM_SLEEP) != 0) {
589 		kmem_free(packbuf, len);
590 		return (EINVAL);
591 	}
592 
593 	/*
594 	 * The nvlist has been unpacked so there is no need for the packed
595 	 * representation from this point on.
596 	 */
597 	kmem_free(packbuf, len);
598 
599 	i = 0;
600 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
601 		switch (nvpair_type(nvp)) {
602 		case DATA_TYPE_UINT32:
603 			if (strcmp(nvpair_name(nvp), "flags") != 0 ||
604 			    nvpair_value_uint32(nvp, &setflags) != 0) {
605 				nvlist_free(nvl);
606 				return (EINVAL);
607 			}
608 			break;
609 		case DATA_TYPE_NVLIST_ARRAY:
610 			if (strcmp(nvpair_name(nvp), "reqs") != 0 ||
611 			    nvpair_value_nvlist_array(nvp, &reqlist,
612 				&nreqs) != 0) {
613 				nvlist_free(nvl);
614 				return (EINVAL);
615 			}
616 			break;
617 		default:
618 			nvlist_free(nvl);
619 			return (EINVAL);
620 		}
621 		i++;
622 	}
623 
624 	/*
625 	 * There should be two members in the top-level nvlist:
626 	 * an array of nvlists consisting of the requests, and flags.
627 	 * Anything else is an invalid set.
628 	 */
629 	if (i != 2) {
630 		nvlist_free(nvl);
631 		return (EINVAL);
632 	}
633 
634 	if (nreqs > CPC_MAX_NREQS) {
635 		nvlist_free(nvl);
636 		return (EINVAL);
637 	}
638 
639 	/*
640 	 * The requests are now stored in the nvlist array at reqlist.
641 	 */
642 	set = kmem_alloc(sizeof (kcpc_set_t), KM_SLEEP);
643 	set->ks_req = (kcpc_request_t *)kmem_zalloc(sizeof (kcpc_request_t) *
644 	    nreqs, KM_SLEEP);
645 	set->ks_nreqs = nreqs;
646 	/*
647 	 * If the nvlist didn't contain a flags member, setflags was initialized
648 	 * with an illegal value and this set will fail sanity checks later on.
649 	 */
650 	set->ks_flags = setflags;
651 
652 	/*
653 	 * Build the set up one request at a time, always keeping it self-
654 	 * consistent so we can give it to kcpc_free_set() if we need to back
655 	 * out and return and error.
656 	 */
657 	for (i = 0; i < nreqs; i++) {
658 		nvp = NULL;
659 		set->ks_req[i].kr_picnum = -1;
660 		while ((nvp = nvlist_next_nvpair(reqlist[i], nvp)) != NULL) {
661 			name = nvpair_name(nvp);
662 			switch (nvpair_type(nvp)) {
663 			case DATA_TYPE_UINT32:
664 				if (nvpair_value_uint32(nvp, &uint32) == EINVAL)
665 					goto inval;
666 				if (strcmp(name, "cr_flags") == 0)
667 					set->ks_req[i].kr_flags = uint32;
668 				if (strcmp(name, "cr_index") == 0)
669 					set->ks_req[i].kr_index = uint32;
670 				break;
671 			case DATA_TYPE_UINT64:
672 				if (nvpair_value_uint64(nvp, &uint64) == EINVAL)
673 					goto inval;
674 				if (strcmp(name, "cr_preset") == 0)
675 					set->ks_req[i].kr_preset = uint64;
676 				break;
677 			case DATA_TYPE_STRING:
678 				if (nvpair_value_string(nvp, &string) == EINVAL)
679 					goto inval;
680 				if (strcmp(name, "cr_event") == 0)
681 					(void) strncpy(set->ks_req[i].kr_event,
682 					    string, CPC_MAX_EVENT_LEN);
683 				break;
684 			case DATA_TYPE_NVLIST:
685 				if (strcmp(name, "cr_attr") != 0)
686 					goto inval;
687 				if (nvpair_value_nvlist(nvp, &attrs) == EINVAL)
688 					goto inval;
689 				nvp_attr = NULL;
690 				/*
691 				 * If the picnum has been specified as an
692 				 * attribute, consume that attribute here and
693 				 * remove it from the list of attributes.
694 				 */
695 				if (nvlist_lookup_uint64(attrs, "picnum",
696 				    &uint64) == 0) {
697 					if (nvlist_remove(attrs, "picnum",
698 					    DATA_TYPE_UINT64) != 0)
699 						panic("nvlist %p faulty",
700 						    attrs);
701 					set->ks_req[i].kr_picnum = uint64;
702 				}
703 
704 				if ((set->ks_req[i].kr_nattrs =
705 				    kcpc_nvlist_npairs(attrs)) == 0)
706 					break;
707 
708 				if (set->ks_req[i].kr_nattrs > CPC_MAX_ATTRS)
709 					goto inval;
710 
711 				set->ks_req[i].kr_attr =
712 				    kmem_alloc(set->ks_req[i].kr_nattrs *
713 				    sizeof (kcpc_attr_t), KM_SLEEP);
714 				j = 0;
715 
716 				while ((nvp_attr = nvlist_next_nvpair(attrs,
717 				    nvp_attr)) != NULL) {
718 					attrp = &set->ks_req[i].kr_attr[j];
719 
720 					if (nvpair_type(nvp_attr) !=
721 					    DATA_TYPE_UINT64)
722 						goto inval;
723 
724 					(void) strncpy(attrp->ka_name,
725 					    nvpair_name(nvp_attr),
726 					    CPC_MAX_ATTR_LEN);
727 
728 					if (nvpair_value_uint64(nvp_attr,
729 					    &(attrp->ka_val)) == EINVAL)
730 						goto inval;
731 					j++;
732 				}
733 				ASSERT(j == set->ks_req[i].kr_nattrs);
734 			default:
735 				break;
736 			}
737 		}
738 	}
739 
740 	nvlist_free(nvl);
741 	*inset = set;
742 	return (0);
743 
744 inval:
745 	nvlist_free(nvl);
746 	kcpc_free_set(set);
747 	return (EINVAL);
748 }
749 
750 /*
751  * Count the number of nvpairs in the supplied nvlist.
752  */
753 static uint32_t
754 kcpc_nvlist_npairs(nvlist_t *list)
755 {
756 	nvpair_t *nvp = NULL;
757 	uint32_t n = 0;
758 
759 	while ((nvp = nvlist_next_nvpair(list, nvp)) != NULL)
760 		n++;
761 
762 	return (n);
763 }
764 
765 /*
766  * Performs sanity checks on the given set.
767  * Returns 0 if the set checks out OK.
768  * Returns a detailed error subcode, or -1 if there is no applicable subcode.
769  */
770 static int
771 kcpc_verify_set(kcpc_set_t *set)
772 {
773 	kcpc_request_t	*rp;
774 	int		i;
775 	uint64_t	bitmap = 0;
776 	int		n;
777 
778 	if (set->ks_nreqs > cpc_ncounters)
779 		return (-1);
780 
781 	if (CPC_SET_VALID_FLAGS(set->ks_flags) == 0)
782 		return (-1);
783 
784 	for (i = 0; i < set->ks_nreqs; i++) {
785 		rp = &set->ks_req[i];
786 
787 		/*
788 		 * The following comparison must cast cpc_ncounters to an int,
789 		 * because kr_picnum will be -1 if the request didn't explicitly
790 		 * choose a PIC.
791 		 */
792 		if (rp->kr_picnum >= (int)cpc_ncounters)
793 			return (CPC_INVALID_PICNUM);
794 
795 		/*
796 		 * Of the pics whose physical picnum has been specified, make
797 		 * sure each PIC appears only once in set.
798 		 */
799 		if ((n = set->ks_req[i].kr_picnum) != -1) {
800 			if ((bitmap & (1 << n)) != 0)
801 				return (-1);
802 			bitmap |= (1 << n);
803 		}
804 
805 		/*
806 		 * Make sure the requested index falls within the range of all
807 		 * requests.
808 		 */
809 		if (rp->kr_index < 0 || rp->kr_index >= set->ks_nreqs)
810 			return (-1);
811 
812 		/*
813 		 * Make sure there are no unknown flags.
814 		 */
815 		if (KCPC_REQ_VALID_FLAGS(rp->kr_flags) == 0)
816 			return (CPC_REQ_INVALID_FLAGS);
817 	}
818 
819 	return (0);
820 }
821 
822 static struct cb_ops cb_ops = {
823 	kcpc_open,
824 	kcpc_close,
825 	nodev,		/* strategy */
826 	nodev,		/* print */
827 	nodev,		/* dump */
828 	nodev,		/* read */
829 	nodev,		/* write */
830 	kcpc_ioctl,
831 	nodev,		/* devmap */
832 	nodev,		/* mmap */
833 	nodev,		/* segmap */
834 	nochpoll,	/* poll */
835 	ddi_prop_op,
836 	NULL,
837 	D_NEW | D_MP
838 };
839 
840 /*ARGSUSED*/
841 static int
842 kcpc_probe(dev_info_t *devi)
843 {
844 	return (DDI_PROBE_SUCCESS);
845 }
846 
847 static dev_info_t *kcpc_devi;
848 
849 static int
850 kcpc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
851 {
852 	if (cmd != DDI_ATTACH)
853 		return (DDI_FAILURE);
854 	kcpc_devi = devi;
855 	return (ddi_create_minor_node(devi, "shared", S_IFCHR,
856 	    KCPC_MINOR_SHARED, DDI_PSEUDO, 0));
857 }
858 
859 /*ARGSUSED*/
860 static int
861 kcpc_getinfo(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, void **result)
862 {
863 	switch (cmd) {
864 	case DDI_INFO_DEVT2DEVINFO:
865 		switch (getminor((dev_t)arg)) {
866 		case KCPC_MINOR_SHARED:
867 			*result = kcpc_devi;
868 			return (DDI_SUCCESS);
869 		default:
870 			break;
871 		}
872 		break;
873 	case DDI_INFO_DEVT2INSTANCE:
874 		*result = 0;
875 		return (DDI_SUCCESS);
876 	default:
877 		break;
878 	}
879 
880 	return (DDI_FAILURE);
881 }
882 
883 static struct dev_ops dev_ops = {
884 	DEVO_REV,
885 	0,
886 	kcpc_getinfo,
887 	nulldev,		/* identify */
888 	kcpc_probe,
889 	kcpc_attach,
890 	nodev,			/* detach */
891 	nodev,			/* reset */
892 	&cb_ops,
893 	(struct bus_ops *)0
894 };
895 
896 static struct modldrv modldrv = {
897 	&mod_driverops,
898 	"cpc sampling driver v%I%",
899 	&dev_ops
900 };
901 
902 static struct sysent cpc_sysent = {
903 	5,
904 	SE_NOUNLOAD | SE_ARGC | SE_32RVAL1,
905 	cpc
906 };
907 
908 static struct modlsys modlsys = {
909 	&mod_syscallops,
910 	"cpc sampling system call",
911 	&cpc_sysent
912 };
913 
914 #ifdef _SYSCALL32_IMPL
915 static struct modlsys modlsys32 = {
916 	&mod_syscallops32,
917 	"32-bit cpc sampling system call",
918 	&cpc_sysent
919 };
920 #endif
921 
922 static struct modlinkage modl = {
923 	MODREV_1,
924 	&modldrv,
925 	&modlsys,
926 #ifdef _SYSCALL32_IMPL
927 	&modlsys32,
928 #endif
929 };
930 
931 static void
932 kcpc_init(void)
933 {
934 	long hash;
935 
936 	rw_init(&kcpc_cpuctx_lock, NULL, RW_DEFAULT, NULL);
937 	for (hash = 0; hash < CPC_HASH_BUCKETS; hash++)
938 		mutex_init(&kcpc_ctx_llock[hash],
939 		    NULL, MUTEX_DRIVER, (void *)(uintptr_t)15);
940 }
941 
942 static void
943 kcpc_fini(void)
944 {
945 	long hash;
946 
947 	for (hash = 0; hash < CPC_HASH_BUCKETS; hash++)
948 		mutex_destroy(&kcpc_ctx_llock[hash]);
949 	rw_destroy(&kcpc_cpuctx_lock);
950 }
951 
952 int
953 _init(void)
954 {
955 	int ret;
956 
957 	if (kcpc_hw_load_pcbe() != 0)
958 		return (ENOTSUP);
959 
960 	kcpc_init();
961 	if ((ret = mod_install(&modl)) != 0)
962 		kcpc_fini();
963 	return (ret);
964 }
965 
966 int
967 _fini(void)
968 {
969 	int ret;
970 
971 	if ((ret = mod_remove(&modl)) == 0)
972 		kcpc_fini();
973 	return (ret);
974 }
975 
976 int
977 _info(struct modinfo *mi)
978 {
979 	return (mod_info(&modl, mi));
980 }
981