xref: /titanic_41/usr/src/uts/sun4v/io/ds_pri.c (revision c6698ca1e2450f37cc5ee4cdded3e5472088ba41)
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  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 /*
26  * sun4v domain services PRI driver
27  */
28 
29 #include <sys/types.h>
30 #include <sys/file.h>
31 #include <sys/errno.h>
32 #include <sys/open.h>
33 #include <sys/cred.h>
34 #include <sys/uio.h>
35 #include <sys/stat.h>
36 #include <sys/ksynch.h>
37 #include <sys/modctl.h>
38 #include <sys/conf.h>
39 #include <sys/devops.h>
40 #include <sys/debug.h>
41 #include <sys/cmn_err.h>
42 #include <sys/ddi.h>
43 #include <sys/sunddi.h>
44 #include <sys/ds.h>
45 #include <sys/hypervisor_api.h>
46 #include <sys/machsystm.h>
47 #include <sys/sysmacros.h>
48 #include <sys/hsvc.h>
49 #include <sys/bitmap.h>
50 #include <sys/ds_pri.h>
51 
52 static uint_t ds_pri_debug = 0;
53 #define	DS_PRI_DBG	if (ds_pri_debug) printf
54 
55 #define	DS_PRI_NAME	"ds_pri"
56 
57 #define	TEST_HARNESS
58 #ifdef TEST_HARNESS
59 #define	DS_PRI_MAX_PRI_SIZE	(64 * 1024)
60 
61 #define	DSIOC_TEST_REG	97
62 #define	DSIOC_TEST_UNREG	98
63 #define	DSIOC_TEST_DATA	99
64 
65 struct ds_pri_test_data {
66 	size_t		size;
67 	void		*data;
68 };
69 
70 struct ds_pri_test_data32 {
71 	size32_t	size;
72 	caddr32_t	data;
73 };
74 #endif /* TEST_HARNESS */
75 
76 typedef	enum {
77 	DS_PRI_REQUEST	= 0,
78 	DS_PRI_DATA	= 1,
79 	DS_PRI_UPDATE	= 2
80 } ds_pri_msg_type_t;
81 
82 typedef	struct {
83 	struct {
84 		uint64_t	seq_num;
85 		uint64_t	type;
86 	} hdr;
87 	uint8_t		data[1];
88 } ds_pri_msg_t;
89 
90 /*
91  * The following are bit field flags. No service implies no DS PRI and
92  * no outstanding request.
93  */
94 typedef enum {
95 	DS_PRI_NO_SERVICE = 0x0,
96 	DS_PRI_HAS_SERVICE = 0x1,
97 	DS_PRI_REQUESTED = 0x2,
98 	DS_PRI_HAS_PRI = 0x4
99 } ds_pri_flags_t;
100 
101 struct ds_pri_state {
102 	dev_info_t	*dip;
103 	int		instance;
104 
105 	kmutex_t	lock;
106 	kcondvar_t	cv;
107 
108 	/* PRI/DS */
109 	ds_pri_flags_t	state;
110 	uint64_t	gencount;
111 	ds_svc_hdl_t	ds_pri_handle;
112 	void		*ds_pri;
113 	size_t		ds_pri_len;
114 	uint64_t	req_id;
115 	uint64_t	last_req_id;
116 	int		num_opens;
117 };
118 
119 typedef struct ds_pri_state ds_pri_state_t;
120 
121 static void *ds_pri_statep;
122 
123 static void request_pri(ds_pri_state_t *sp);
124 static uint64_t ds_get_hv_pri(ds_pri_state_t *sp);
125 
126 static int ds_pri_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
127 static int ds_pri_attach(dev_info_t *, ddi_attach_cmd_t);
128 static int ds_pri_detach(dev_info_t *, ddi_detach_cmd_t);
129 static int ds_pri_open(dev_t *, int, int, cred_t *);
130 static int ds_pri_close(dev_t, int, int, cred_t *);
131 static int ds_pri_read(dev_t, struct uio *, cred_t *);
132 static int ds_pri_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
133 
134 /*
135  * DS Callbacks
136  */
137 static void ds_pri_reg_handler(ds_cb_arg_t, ds_ver_t *, ds_svc_hdl_t);
138 static void ds_pri_unreg_handler(ds_cb_arg_t arg);
139 static void ds_pri_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen);
140 
141 /*
142  * PRI DS capability registration
143  */
144 
145 static ds_ver_t ds_pri_ver_1_0 = { 1, 0 };
146 
147 static ds_capability_t ds_pri_cap = {
148 	"pri",
149 	&ds_pri_ver_1_0,
150 	1
151 };
152 
153 /*
154  * PRI DS Client callback vector
155  */
156 static ds_clnt_ops_t ds_pri_ops = {
157 	ds_pri_reg_handler,	/* ds_reg_cb */
158 	ds_pri_unreg_handler,	/* ds_unreg_cb */
159 	ds_pri_data_handler,	/* ds_data_cb */
160 	NULL			/* cb_arg */
161 };
162 
163 /*
164  * DS PRI driver Ops Vector
165  */
166 static struct cb_ops ds_pri_cb_ops = {
167 	ds_pri_open,		/* cb_open */
168 	ds_pri_close,		/* cb_close */
169 	nodev,			/* cb_strategy */
170 	nodev,			/* cb_print */
171 	nodev,			/* cb_dump */
172 	ds_pri_read,		/* cb_read */
173 	nodev,			/* cb_write */
174 	ds_pri_ioctl,		/* cb_ioctl */
175 	nodev,			/* cb_devmap */
176 	nodev,			/* cb_mmap */
177 	nodev,			/* cb_segmap */
178 	nochpoll,		/* cb_chpoll */
179 	ddi_prop_op,		/* cb_prop_op */
180 	(struct streamtab *)NULL, /* cb_str */
181 	D_MP | D_64BIT,		/* cb_flag */
182 	CB_REV,			/* cb_rev */
183 	nodev,			/* cb_aread */
184 	nodev			/* cb_awrite */
185 };
186 
187 static struct dev_ops ds_pri_dev_ops = {
188 	DEVO_REV,		/* devo_rev */
189 	0,			/* devo_refcnt */
190 	ds_pri_getinfo,		/* devo_getinfo */
191 	nulldev,		/* devo_identify */
192 	nulldev,		/* devo_probe */
193 	ds_pri_attach,		/* devo_attach */
194 	ds_pri_detach,		/* devo_detach */
195 	nodev,			/* devo_reset */
196 	&ds_pri_cb_ops,		/* devo_cb_ops */
197 	(struct bus_ops *)NULL,	/* devo_bus_ops */
198 	nulldev,		/* devo_power */
199 	ddi_quiesce_not_needed,		/* devo_quiesce */
200 };
201 
202 static struct modldrv modldrv = {
203 	&mod_driverops,
204 	"Domain Services PRI Driver",
205 	&ds_pri_dev_ops
206 };
207 
208 static struct modlinkage modlinkage = {
209 	MODREV_1,
210 	(void *)&modldrv,
211 	NULL
212 };
213 
214 static boolean_t hsvc_pboot_available = B_FALSE;
215 static hsvc_info_t pboot_hsvc = {
216 	HSVC_REV_1, NULL, HSVC_GROUP_PBOOT, 1, 0, NULL
217 };
218 
219 int
220 _init(void)
221 {
222 	int retval;
223 	uint64_t	hsvc_pboot_minor;
224 	uint64_t	status;
225 
226 	status = hsvc_register(&pboot_hsvc, &hsvc_pboot_minor);
227 	if (status == H_EOK) {
228 		hsvc_pboot_available = B_TRUE;
229 	} else {
230 		DS_PRI_DBG("hypervisor services not negotiated "
231 		    "for group number: 0x%lx errorno: 0x%lx\n",
232 		    pboot_hsvc.hsvc_group, status);
233 	}
234 
235 	retval = ddi_soft_state_init(&ds_pri_statep,
236 	    sizeof (ds_pri_state_t), 0);
237 	if (retval != 0)
238 		return (retval);
239 
240 	retval = mod_install(&modlinkage);
241 	if (retval != 0) {
242 		ddi_soft_state_fini(&ds_pri_statep);
243 		return (retval);
244 	}
245 
246 	return (retval);
247 }
248 
249 
250 int
251 _info(struct modinfo *modinfop)
252 {
253 	return (mod_info(&modlinkage, modinfop));
254 }
255 
256 
257 int
258 _fini(void)
259 {
260 	int retval;
261 
262 	if ((retval = mod_remove(&modlinkage)) != 0)
263 		return (retval);
264 
265 	ddi_soft_state_fini(&ds_pri_statep);
266 
267 	if (hsvc_pboot_available)
268 		(void) hsvc_unregister(&pboot_hsvc);
269 
270 	return (retval);
271 }
272 
273 
274 /*ARGSUSED*/
275 static int
276 ds_pri_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
277 {
278 	ds_pri_state_t *sp;
279 	int retval = DDI_FAILURE;
280 
281 	ASSERT(resultp != NULL);
282 
283 	switch (cmd) {
284 	case DDI_INFO_DEVT2DEVINFO:
285 		sp = ddi_get_soft_state(ds_pri_statep, getminor((dev_t)arg));
286 		if (sp != NULL) {
287 			*resultp = sp->dip;
288 			retval = DDI_SUCCESS;
289 		} else
290 			*resultp = NULL;
291 		break;
292 
293 	case DDI_INFO_DEVT2INSTANCE:
294 		*resultp = (void *)(uintptr_t)getminor((dev_t)arg);
295 		retval = DDI_SUCCESS;
296 		break;
297 
298 	default:
299 		break;
300 	}
301 
302 	return (retval);
303 }
304 
305 
306 static int
307 ds_pri_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
308 {
309 	int instance;
310 	ds_pri_state_t *sp;
311 	int rv;
312 	uint64_t status;
313 
314 	switch (cmd) {
315 	case DDI_ATTACH:
316 		break;
317 
318 	case DDI_RESUME:
319 		return (DDI_SUCCESS);
320 
321 	default:
322 		return (DDI_FAILURE);
323 	}
324 
325 	instance = ddi_get_instance(dip);
326 
327 	if (ddi_soft_state_zalloc(ds_pri_statep, instance) !=
328 	    DDI_SUCCESS) {
329 		cmn_err(CE_WARN, "%s@%d: Unable to allocate state",
330 		    DS_PRI_NAME, instance);
331 		return (DDI_FAILURE);
332 	}
333 	sp = ddi_get_soft_state(ds_pri_statep, instance);
334 
335 	mutex_init(&sp->lock, NULL, MUTEX_DEFAULT, NULL);
336 	cv_init(&sp->cv, NULL, CV_DEFAULT, NULL);
337 
338 	if (ddi_create_minor_node(dip, DS_PRI_NAME, S_IFCHR, instance,
339 	    DDI_PSEUDO, 0) != DDI_SUCCESS) {
340 		cmn_err(CE_WARN, "%s@%d: Unable to create minor node",
341 		    DS_PRI_NAME, instance);
342 		goto fail;
343 	}
344 
345 	if (ds_pri_ops.cb_arg != NULL)
346 		goto fail;
347 	ds_pri_ops.cb_arg = dip;
348 
349 	sp->state = DS_PRI_NO_SERVICE;
350 
351 	/* Until the service registers the handle is invalid */
352 	sp->ds_pri_handle = DS_INVALID_HDL;
353 
354 	sp->ds_pri = NULL;
355 	sp->ds_pri_len = 0;
356 	sp->req_id = 0;
357 	sp->num_opens = 0;
358 
359 	/*
360 	 * See if we can get the static hv pri data. Static pri data
361 	 * is only available for privileged domains.
362 	 */
363 	if (hsvc_pboot_available) {
364 		if ((status = ds_get_hv_pri(sp)) != 0) {
365 			cmn_err(CE_NOTE, "ds_get_hv_pri failed: 0x%lx", status);
366 		}
367 	}
368 
369 	if ((rv = ds_cap_init(&ds_pri_cap, &ds_pri_ops)) != 0) {
370 		cmn_err(CE_NOTE, "ds_cap_init failed: %d", rv);
371 		goto fail;
372 	}
373 
374 	ddi_report_dev(dip);
375 
376 	return (DDI_SUCCESS);
377 
378 fail:
379 	if (sp->ds_pri)
380 		kmem_free(sp->ds_pri, sp->ds_pri_len);
381 	ddi_remove_minor_node(dip, NULL);
382 	cv_destroy(&sp->cv);
383 	mutex_destroy(&sp->lock);
384 	ddi_soft_state_free(ds_pri_statep, instance);
385 	return (DDI_FAILURE);
386 
387 }
388 
389 
390 /*ARGSUSED*/
391 static int
392 ds_pri_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
393 {
394 	ds_pri_state_t *sp;
395 	int instance;
396 	int rv;
397 
398 	instance = ddi_get_instance(dip);
399 	sp = ddi_get_soft_state(ds_pri_statep, instance);
400 
401 	switch (cmd) {
402 	case DDI_DETACH:
403 		break;
404 
405 	case DDI_SUSPEND:
406 		return (DDI_SUCCESS);
407 
408 	default:
409 		return (DDI_FAILURE);
410 	}
411 
412 	/* This really shouldn't fail - but check anyway */
413 	if ((rv = ds_cap_fini(&ds_pri_cap)) != 0) {
414 		cmn_err(CE_WARN, "ds_cap_fini failed: %d", rv);
415 	}
416 
417 	if (sp != NULL && sp->ds_pri_len != 0)
418 		kmem_free(sp->ds_pri, sp->ds_pri_len);
419 
420 	ds_pri_ops.cb_arg = NULL;
421 
422 	ddi_remove_minor_node(dip, NULL);
423 	cv_destroy(&sp->cv);
424 	mutex_destroy(&sp->lock);
425 	ddi_soft_state_free(ds_pri_statep, instance);
426 
427 	return (DDI_SUCCESS);
428 }
429 
430 
431 /*ARGSUSED*/
432 static int
433 ds_pri_open(dev_t *devp, int flag, int otyp, cred_t *credp)
434 {
435 	ds_pri_state_t *sp;
436 	int instance;
437 
438 	if (otyp != OTYP_CHR)
439 		return (EINVAL);
440 
441 	instance = getminor(*devp);
442 	sp = ddi_get_soft_state(ds_pri_statep, instance);
443 	if (sp == NULL)
444 		return (ENXIO);
445 
446 	mutex_enter(&sp->lock);
447 
448 	/*
449 	 * Proceed if we have PRI data (possibly obtained from
450 	 * static HV PRI or last pushed DS PRI data update).
451 	 * If no PRI data and we have no DS PRI service then this
452 	 * means that PRI DS has never called the registration callback.
453 	 * A while loop is necessary as we might have been woken up
454 	 * prematurely, e.g., due to a debugger or "pstack" etc.
455 	 * Wait here and the callback will signal us when it has completed
456 	 * its work.
457 	 */
458 	if (!(sp->state & DS_PRI_HAS_PRI)) {
459 		while (!(sp->state & DS_PRI_HAS_SERVICE)) {
460 			if (cv_wait_sig(&sp->cv, &sp->lock) == 0) {
461 				mutex_exit(&sp->lock);
462 				return (EINTR);
463 			}
464 		}
465 	}
466 
467 	sp->num_opens++;
468 	mutex_exit(&sp->lock);
469 
470 	DS_PRI_DBG("ds_pri_open: state = 0x%x\n", sp->state);
471 
472 	return (0);
473 }
474 
475 
476 /*ARGSUSED*/
477 static int
478 ds_pri_close(dev_t dev, int flag, int otyp, cred_t *credp)
479 {
480 	int instance;
481 	ds_pri_state_t *sp;
482 
483 	if (otyp != OTYP_CHR)
484 		return (EINVAL);
485 
486 	DS_PRI_DBG("ds_pri_close\n");
487 
488 	instance = getminor(dev);
489 	if ((sp = ddi_get_soft_state(ds_pri_statep, instance)) == NULL)
490 		return (ENXIO);
491 
492 	mutex_enter(&sp->lock);
493 	if (!(sp->state & DS_PRI_HAS_SERVICE)) {
494 		mutex_exit(&sp->lock);
495 		return (0);
496 	}
497 
498 	if (--sp->num_opens > 0) {
499 		mutex_exit(&sp->lock);
500 		return (0);
501 	}
502 
503 	sp->state &= ~DS_PRI_REQUESTED;
504 	mutex_exit(&sp->lock);
505 	return (0);
506 }
507 
508 
509 /*ARGSUSED*/
510 static int
511 ds_pri_read(dev_t dev, struct uio *uiop, cred_t *credp)
512 {
513 	ds_pri_state_t *sp;
514 	int instance;
515 	size_t len;
516 	int retval;
517 	caddr_t tmpbufp;
518 	offset_t off = uiop->uio_offset;
519 
520 	instance = getminor(dev);
521 	if ((sp = ddi_get_soft_state(ds_pri_statep, instance)) == NULL)
522 		return (ENXIO);
523 
524 	len = uiop->uio_resid;
525 
526 	if (len == 0)
527 		return (0);
528 
529 	mutex_enter(&sp->lock);
530 
531 	DS_PRI_DBG("ds_pri_read: state = 0x%x\n", sp->state);
532 
533 	/* block or bail if there is no current PRI */
534 	if (!(sp->state & DS_PRI_HAS_PRI)) {
535 		DS_PRI_DBG("ds_pri_read: no PRI held\n");
536 
537 		if (uiop->uio_fmode & (FNDELAY | FNONBLOCK)) {
538 			mutex_exit(&sp->lock);
539 			return (EAGAIN);
540 		}
541 
542 		while (!(sp->state & DS_PRI_HAS_PRI)) {
543 			DS_PRI_DBG("ds_pri_read: state = 0x%x\n", sp->state);
544 			request_pri(sp);
545 			if (cv_wait_sig(&sp->cv, &sp->lock) == 0) {
546 				mutex_exit(&sp->lock);
547 				return (EINTR);
548 			}
549 		}
550 	}
551 
552 	if (len > sp->ds_pri_len)
553 		len = sp->ds_pri_len;
554 
555 	if (len == 0) {
556 		mutex_exit(&sp->lock);
557 		return (0);
558 	}
559 
560 	/*
561 	 * We're supposed to move the data out to userland, but
562 	 * that can suspend because of page faults etc., and meanwhile
563 	 * other parts of this driver want to update the PRI buffer ...
564 	 * we could hold the data buffer locked with a flag etc.,
565 	 * but that's still a lock ... a simpler mechanism - if not quite
566 	 * as performance efficient is to simply clone here the part of
567 	 * the buffer we care about and then the original can be released
568 	 * for further updates while the uiomove continues.
569 	 */
570 
571 	tmpbufp = kmem_alloc(len, KM_SLEEP);
572 	bcopy(((caddr_t)sp->ds_pri), tmpbufp, len);
573 	mutex_exit(&sp->lock);
574 
575 	retval = uiomove(tmpbufp, len, UIO_READ, uiop);
576 
577 	kmem_free(tmpbufp, len);
578 
579 	/*
580 	 * restore uio_offset after uiomove since the driver
581 	 * does not support the concept of position.
582 	 */
583 	uiop->uio_offset = off;
584 
585 	return (retval);
586 }
587 
588 
589 /*ARGSUSED*/
590 static int
591 ds_pri_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
592     int *rvalp)
593 {
594 	ds_pri_state_t *sp;
595 	int instance;
596 
597 	instance = getminor(dev);
598 	if ((sp = ddi_get_soft_state(ds_pri_statep, instance)) == NULL)
599 		return (ENXIO);
600 
601 	switch (cmd) {
602 	case DSPRI_GETINFO: {
603 		struct dspri_info info;
604 
605 		if (!(mode & FREAD))
606 			return (EACCES);
607 
608 		/*
609 		 * We are not guaranteed that ddi_copyout(9F) will read
610 		 * atomically anything larger than a byte.  Therefore we
611 		 * must duplicate the size before copying it out to the user.
612 		 */
613 		mutex_enter(&sp->lock);
614 
615 loop:;
616 		if (sp->state & DS_PRI_HAS_PRI) {
617 			/* If we have a PRI simply return the info */
618 			info.size = sp->ds_pri_len;
619 			info.token = sp->gencount;
620 		} else
621 		if (!(sp->state & DS_PRI_HAS_SERVICE)) {
622 			/* If we have no service return a nil response */
623 			info.size = 0;
624 			info.token = 0;
625 		} else {
626 			request_pri(sp);
627 			/* wait for something & check again */
628 			if (cv_wait_sig(&sp->cv, &sp->lock) == 0) {
629 				mutex_exit(&sp->lock);
630 				return (EINTR);
631 			}
632 			goto loop;
633 		}
634 		DS_PRI_DBG("ds_pri_ioctl: DSPRI_GETINFO sz=0x%lx tok=0x%lx\n",
635 		    info.size, info.token);
636 		mutex_exit(&sp->lock);
637 
638 		if (ddi_copyout(&info, (void *)arg, sizeof (info), mode) != 0)
639 			return (EFAULT);
640 		break;
641 	}
642 
643 	case DSPRI_WAIT: {
644 		uint64_t gencount;
645 
646 		if (ddi_copyin((void *)arg, &gencount, sizeof (gencount),
647 		    mode) != 0)
648 			return (EFAULT);
649 
650 		mutex_enter(&sp->lock);
651 
652 		DS_PRI_DBG("ds_pri_ioctl: DSPRI_WAIT gen=0x%lx sp->gen=0x%lx\n",
653 		    gencount, sp->gencount);
654 
655 		while ((sp->state & DS_PRI_HAS_PRI) == 0 ||
656 		    gencount == sp->gencount) {
657 			if ((sp->state & DS_PRI_HAS_PRI) == 0)
658 				request_pri(sp);
659 			if (cv_wait_sig(&sp->cv, &sp->lock) == 0) {
660 				mutex_exit(&sp->lock);
661 				return (EINTR);
662 			}
663 		}
664 		mutex_exit(&sp->lock);
665 		break;
666 	}
667 
668 	default:
669 		return (ENOTTY);
670 	}
671 	return (0);
672 }
673 
674 
675 	/* assumes sp->lock is held when called */
676 static void
677 request_pri(ds_pri_state_t *sp)
678 {
679 	ds_pri_msg_t reqmsg;
680 
681 	ASSERT(MUTEX_HELD(&sp->lock));
682 
683 	/* If a request is already pending we're done */
684 	if (!(sp->state & DS_PRI_HAS_SERVICE))
685 		return;
686 	if (sp->state & DS_PRI_REQUESTED)
687 		return;
688 
689 	/* If we have an old PRI - remove it */
690 	if (sp->state & DS_PRI_HAS_PRI) {
691 		ASSERT(sp->ds_pri_len != 0);
692 		ASSERT(sp->ds_pri != NULL);
693 
694 		/* remove the old data if we have an outstanding request */
695 		kmem_free(sp->ds_pri, sp->ds_pri_len);
696 		sp->ds_pri_len = 0;
697 		sp->ds_pri = NULL;
698 		sp->state &= ~DS_PRI_HAS_PRI;
699 	} else {
700 		ASSERT(sp->ds_pri == NULL);
701 		ASSERT(sp->ds_pri_len == 0);
702 	}
703 
704 	reqmsg.hdr.seq_num = ++(sp->req_id);
705 	reqmsg.hdr.type = DS_PRI_REQUEST;
706 
707 	DS_PRI_DBG("request_pri: request id 0x%lx\n", sp->req_id);
708 
709 		/*
710 		 * Request consists of header only.
711 		 * We don't care about fail status for ds_send;
712 		 * if it does fail we will get an unregister callback
713 		 * from the DS framework and we handle the state change
714 		 * there.
715 		 */
716 	(void) ds_cap_send(sp->ds_pri_handle, &reqmsg, sizeof (reqmsg.hdr));
717 
718 	sp->state |= DS_PRI_REQUESTED;
719 	sp->last_req_id = sp->req_id;
720 }
721 
722 /*
723  * DS Callbacks
724  */
725 /*ARGSUSED*/
726 static void
727 ds_pri_reg_handler(ds_cb_arg_t arg, ds_ver_t *ver, ds_svc_hdl_t hdl)
728 {
729 	dev_info_t *dip = arg;
730 	ds_pri_state_t *sp;
731 	int instance;
732 
733 	instance = ddi_get_instance(dip);
734 	if ((sp = ddi_get_soft_state(ds_pri_statep, instance)) == NULL)
735 		return;
736 
737 	DS_PRI_DBG("ds_pri_reg_handler: registering handle 0x%lx for version "
738 	    "0x%x:0x%x\n", (uint64_t)hdl, ver->major, ver->minor);
739 
740 	/* When the domain service comes up automatically update the state */
741 	mutex_enter(&sp->lock);
742 
743 	ASSERT(sp->ds_pri_handle == DS_INVALID_HDL);
744 	sp->ds_pri_handle = hdl;
745 
746 	ASSERT(!(sp->state & DS_PRI_HAS_SERVICE));
747 	sp->state |= DS_PRI_HAS_SERVICE;
748 
749 	/*
750 	 * Cannot request a PRI here, because the reg handler cannot
751 	 * do a DS send operation - we take care of this later.
752 	 * Static hv pri data might be available.
753 	 */
754 
755 	/* Wake up anyone waiting in open() */
756 	cv_broadcast(&sp->cv);
757 
758 	mutex_exit(&sp->lock);
759 }
760 
761 
762 static void
763 ds_pri_unreg_handler(ds_cb_arg_t arg)
764 {
765 	dev_info_t *dip = arg;
766 	ds_pri_state_t *sp;
767 	int instance;
768 
769 	instance = ddi_get_instance(dip);
770 	if ((sp = ddi_get_soft_state(ds_pri_statep, instance)) == NULL)
771 		return;
772 
773 	DS_PRI_DBG("ds_pri_unreg_handler: un-registering ds_pri service\n");
774 
775 	mutex_enter(&sp->lock);
776 
777 	/*
778 	 * Note that if the service goes offline, we don't
779 	 * free up the current PRI data at hand. It is assumed
780 	 * that PRI DS service will only push new update when
781 	 * it comes online. We mark the state to indicate no
782 	 * DS PRI service is available. The current PRI data if
783 	 * available is provided to the consumers.
784 	 */
785 	sp->ds_pri_handle = DS_INVALID_HDL;
786 	sp->state &= ~DS_PRI_HAS_SERVICE;
787 
788 	mutex_exit(&sp->lock);
789 }
790 
791 
792 static void
793 ds_pri_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen)
794 {
795 	dev_info_t *dip = arg;
796 	ds_pri_state_t *sp;
797 	int instance;
798 	void *data;
799 	ds_pri_msg_t	*msgp;
800 	size_t	pri_size;
801 
802 	msgp = (ds_pri_msg_t *)buf;
803 
804 	/* make sure the header is at least valid */
805 	if (buflen < sizeof (msgp->hdr))
806 		return;
807 
808 	DS_PRI_DBG("ds_pri_data_handler: msg buf len 0x%lx : type 0x%lx, "
809 	    "seqn 0x%lx\n", buflen, msgp->hdr.type, msgp->hdr.seq_num);
810 
811 	instance = ddi_get_instance(dip);
812 	if ((sp = ddi_get_soft_state(ds_pri_statep, instance)) == NULL)
813 		return;
814 
815 	mutex_enter(&sp->lock);
816 
817 	ASSERT(sp->state & DS_PRI_HAS_SERVICE);
818 
819 	switch (msgp->hdr.type) {
820 	case DS_PRI_DATA:	/* in response to a request from us */
821 		break;
822 	case DS_PRI_UPDATE:	/* aynch notification */
823 			/* our default response to this is to request the PRI */
824 		/* simply issue a request for the new PRI */
825 		request_pri(sp);
826 		goto done;
827 	default:	/* ignore garbage or unknown message types */
828 		goto done;
829 	}
830 
831 	/*
832 	 * If there is no pending PRI request, then we've received a
833 	 * bogus data message ... so ignore it.
834 	 */
835 
836 	if (!(sp->state & DS_PRI_REQUESTED)) {
837 		cmn_err(CE_WARN, "Received DS pri data without request");
838 		goto done;
839 	}
840 
841 	/* response to a request therefore old PRI must be gone */
842 	ASSERT(!(sp->state & DS_PRI_HAS_PRI));
843 	ASSERT(sp->ds_pri_len == 0);
844 	ASSERT(sp->ds_pri == NULL);
845 
846 	/* response seq_num should match our request seq_num */
847 	if (msgp->hdr.seq_num != sp->last_req_id) {
848 		cmn_err(CE_WARN, "Received DS pri data out of sequence with "
849 		    "request");
850 		goto done;
851 	}
852 
853 	pri_size = buflen - sizeof (msgp->hdr);
854 	if (pri_size == 0) {
855 		cmn_err(CE_WARN, "Received DS pri data of size 0");
856 		goto done;
857 	}
858 	data = kmem_alloc(pri_size, KM_SLEEP);
859 	sp->ds_pri = data;
860 	sp->ds_pri_len = pri_size;
861 	bcopy(msgp->data, data, sp->ds_pri_len);
862 	sp->state &= ~DS_PRI_REQUESTED;
863 	sp->state |= DS_PRI_HAS_PRI;
864 
865 	sp->gencount++;
866 	cv_broadcast(&sp->cv);
867 
868 done:;
869 	mutex_exit(&sp->lock);
870 }
871 
872 /*
873  * Routine to get static PRI data from the Hypervisor.
874  * If successful, this PRI data is the last known PRI
875  * data generated since the last poweron reset.
876  */
877 static uint64_t
878 ds_get_hv_pri(ds_pri_state_t *sp)
879 {
880 	uint64_t	status;
881 	uint64_t	pri_size;
882 	uint64_t	buf_size;
883 	uint64_t	buf_pa;
884 	caddr_t		buf_va = NULL;
885 	caddr_t		pri_data;
886 
887 	/*
888 	 * Get pri buffer size by calling hcall with buffer size 0.
889 	 */
890 	pri_size = 0LL;
891 	status = hv_mach_pri((uint64_t)0, &pri_size);
892 	if (status == H_ENOTSUPPORTED || status == H_ENOACCESS) {
893 		/*
894 		 * hv_mach_pri() is not supported on a guest domain.
895 		 * Unregister pboot API group to prevent failures.
896 		 */
897 		(void) hsvc_unregister(&pboot_hsvc);
898 		hsvc_pboot_available = B_FALSE;
899 		DS_PRI_DBG("ds_get_hv_pri: hv_mach_pri service is not "
900 		    "available. errorno: 0x%lx\n", status);
901 		return (0);
902 	} else if (pri_size == 0) {
903 		return (1);
904 	} else {
905 		DS_PRI_DBG("ds_get_hv_pri: hv_mach_pri pri size: 0x%lx\n",
906 		    pri_size);
907 	}
908 
909 	/*
910 	 * contig_mem_alloc requires size to be a power of 2.
911 	 * Increase size to next power of 2 if necessary.
912 	 */
913 	if ((pri_size & (pri_size - 1)) != 0)
914 		buf_size = 1 << highbit(pri_size);
915 	DS_PRI_DBG("ds_get_hv_pri: buf_size = 0x%lx\n", buf_size);
916 
917 	buf_va = contig_mem_alloc(buf_size);
918 	if (buf_va == NULL)
919 		return (1);
920 
921 	buf_pa = va_to_pa(buf_va);
922 	DS_PRI_DBG("ds_get_hv_pri: buf_pa 0x%lx\n", buf_pa);
923 	status = hv_mach_pri(buf_pa, &pri_size);
924 	DS_PRI_DBG("ds_get_hv_pri: hv_mach_pri status = 0x%lx\n", status);
925 
926 	if (status == H_EOK) {
927 		pri_data = kmem_alloc(pri_size, KM_SLEEP);
928 		sp->ds_pri = pri_data;
929 		sp->ds_pri_len = pri_size;
930 		bcopy(buf_va, pri_data, sp->ds_pri_len);
931 		sp->state |= DS_PRI_HAS_PRI;
932 		sp->gencount++;
933 	}
934 
935 	contig_mem_free(buf_va, buf_size);
936 
937 	return (status);
938 }
939