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