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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 #include <sys/time.h> 28 #include <sys/errno.h> 29 #include <sys/kmem.h> 30 #include <sys/stat.h> 31 #include <sys/cmn_err.h> 32 33 #include <sys/conf.h> 34 #include <sys/modctl.h> 35 #include <sys/devops.h> 36 #include <sys/ddi.h> 37 #include <sys/sunddi.h> 38 #include <sys/callb.h> 39 #include <sys/disp.h> 40 #include <sys/strlog.h> 41 #include <sys/file.h> 42 43 #include <sys/uadmin.h> 44 #include <sys/machsystm.h> 45 #include <sys/hypervisor_api.h> 46 #include <sys/hsvc.h> 47 #include <sys/glvc.h> 48 49 /* 50 * Global Variables - can be patched from Solaris 51 * ============================================== 52 */ 53 54 /* bit defination in virtual device register */ 55 #define GLVC_REG_RECV 0x0001 56 #define GLVC_REG_RECV_ENA 0x0002 57 #define GLVC_REG_SEND 0x0004 58 #define GLVC_REG_SEND_ENA 0x0008 59 #define GLVC_REG_ERR 0x8000 60 61 /* 62 * For interrupt mode 63 */ 64 #define GLVC_MODE_NONE 0 65 #define GLVC_POLLING_MODE 1 66 #define GLVC_INTR_MODE 2 67 68 /* 69 * For open 70 */ 71 #define GLVC_NO_OPEN 0 72 #define GLVC_OPEN 1 73 #define GLVC_EXCL_OPEN 2 74 75 /* 76 * For timeout polling, in microsecond. 77 */ 78 #define GLVC_TIMEOUT_POLL 5000000 /* Timeout in intr mode */ 79 #define GLVC_POLLMODE_POLL 500000 /* Interval in polling mode */ 80 81 /* 82 * For debug printing 83 */ 84 #define _PRINTF printf 85 #define DPRINTF(args) if (glvc_debug) _PRINTF args; 86 87 /* 88 * Driver entry points 89 */ 90 static int glvc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 91 static int glvc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 92 static int glvc_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p); 93 static int glvc_close(dev_t dev, int flag, int otyp, cred_t *cred_p); 94 static int glvc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 95 cred_t *cred_p, int *rval_p); 96 static int glvc_read(dev_t dev, struct uio *uiop, cred_t *credp); 97 static int glvc_write(dev_t dev, struct uio *uiop, cred_t *credp); 98 99 static struct cb_ops glvc_cb_ops = { 100 glvc_open, /* open */ 101 glvc_close, /* close */ 102 nodev, /* strategy() */ 103 nodev, /* print() */ 104 nodev, /* dump() */ 105 glvc_read, /* read() */ 106 glvc_write, /* write() */ 107 glvc_ioctl, /* ioctl() */ 108 nodev, /* devmap() */ 109 nodev, /* mmap() */ 110 ddi_segmap, /* segmap() */ 111 nochpoll, /* poll() */ 112 ddi_prop_op, /* prop_op() */ 113 NULL, /* cb_str */ 114 D_NEW | D_MP /* cb_flag */ 115 }; 116 117 118 static struct dev_ops glvc_ops = { 119 DEVO_REV, 120 0, /* ref count */ 121 ddi_getinfo_1to1, /* getinfo() */ 122 nulldev, /* identify() */ 123 nulldev, /* probe() */ 124 glvc_attach, /* attach() */ 125 glvc_detach, /* detach */ 126 nodev, /* reset */ 127 &glvc_cb_ops, /* pointer to cb_ops structure */ 128 (struct bus_ops *)NULL, 129 nulldev, /* power() */ 130 ddi_quiesce_not_needed, /* quiesce */ 131 }; 132 133 /* 134 * Loadable module support. 135 */ 136 extern struct mod_ops mod_driverops; 137 138 static struct modldrv modldrv = { 139 &mod_driverops, /* Type of module. This is a driver */ 140 "Sun4v virtual channel driver", /* Name of the module */ 141 &glvc_ops /* pointer to the dev_ops structure */ 142 }; 143 144 static struct modlinkage modlinkage = { 145 MODREV_1, 146 &modldrv, 147 NULL 148 }; 149 150 typedef struct glvc_soft_state { 151 dev_info_t *dip; /* dev info of myself */ 152 uint64_t s_id; /* service id for this node */ 153 uint64_t mtu; /* max transmit unit size */ 154 uint64_t flag; /* flag register */ 155 kmutex_t open_mutex; /* protect open_state flag */ 156 uint8_t open_state; /* no-open, open or open exclusively */ 157 kmutex_t recv_mutex; 158 kmutex_t send_complete_mutex; 159 uint8_t send_complete_flag; /* 1 = send completed */ 160 uint8_t intr_mode; /* 1 = polling mode, 2 = interrupt mode */ 161 clock_t polling_interval; 162 ddi_softintr_t poll_mode_softint_id; 163 kcondvar_t recv_cv; 164 kcondvar_t send_complete_cv; 165 kmutex_t statusreg_mutex; /* Protects status register */ 166 char *mb_recv_buf; 167 char *mb_send_buf; 168 uint64_t mb_recv_buf_pa; 169 uint64_t mb_send_buf_pa; 170 } glvc_soft_state_t; 171 172 /* 173 * Hypervisor VSC api versioning information for glvc driver. 174 */ 175 static uint64_t glvc_vsc_min_ver; /* Negotiated VSC API minor version */ 176 static uint_t glvc_vsc_users = 0; /* VSC API users */ 177 static kmutex_t glvc_vsc_users_mutex; /* Mutex to protect user count */ 178 179 static hsvc_info_t glvc_hsvc = { 180 HSVC_REV_1, NULL, HSVC_GROUP_VSC, GLVC_VSC_MAJOR_VER, 181 GLVC_VSC_MINOR_VER, "glvc" 182 }; 183 184 /* 185 * Module Variables 186 * ================ 187 */ 188 189 /* 190 * functions local to this driver. 191 */ 192 static int glvc_add_intr_handlers(dev_info_t *dip); 193 static int glvc_remove_intr_handlers(dev_info_t *dip); 194 static uint_t glvc_intr(caddr_t arg); 195 static int glvc_peek(glvc_soft_state_t *softsp, 196 glvc_xport_msg_peek_t *msg_peek); 197 static uint_t glvc_soft_intr(caddr_t arg); 198 static int glvc_emap_h2s(uint64_t hv_errcode); 199 static int glvc_ioctl_opt_op(glvc_soft_state_t *softsp, 200 intptr_t arg, int mode); 201 202 /* 203 * Driver globals 204 */ 205 static void *glvc_ssp; /* pointer to driver soft state */ 206 207 static uint_t glvc_debug = 0; 208 209 int 210 _init(void) 211 { 212 int error = 0; 213 214 if ((error = ddi_soft_state_init(&glvc_ssp, 215 sizeof (glvc_soft_state_t), 1)) != 0) 216 return (error); 217 218 /* 219 * Initialize the mutex for global data structure 220 */ 221 mutex_init(&glvc_vsc_users_mutex, NULL, MUTEX_DRIVER, NULL); 222 223 error = mod_install(&modlinkage); 224 225 return (error); 226 } 227 228 229 int 230 _info(struct modinfo *modinfop) 231 { 232 return (mod_info(&modlinkage, modinfop)); 233 } 234 235 236 int 237 _fini(void) 238 { 239 int error = 0; 240 241 error = mod_remove(&modlinkage); 242 if (error) 243 return (error); 244 245 mutex_destroy(&glvc_vsc_users_mutex); 246 247 ddi_soft_state_fini(&glvc_ssp); 248 return (0); 249 } 250 251 252 static int 253 glvc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 254 { 255 int instance; 256 int err; 257 glvc_soft_state_t *softsp; 258 259 switch (cmd) { 260 case DDI_ATTACH: 261 instance = ddi_get_instance(dip); 262 263 /* 264 * Negotiate the API version for VSC hypervisor services. 265 */ 266 mutex_enter(&glvc_vsc_users_mutex); 267 if (glvc_vsc_users == 0 && 268 (err = hsvc_register(&glvc_hsvc, &glvc_vsc_min_ver)) 269 != 0) { 270 cmn_err(CE_WARN, "%s: cannot negotiate hypervisor " 271 "services group: 0x%lx major: 0x%lx minor: 0x%lx " 272 "errno: %d\n", glvc_hsvc.hsvc_modname, 273 glvc_hsvc.hsvc_group, glvc_hsvc.hsvc_major, 274 glvc_hsvc.hsvc_minor, err); 275 276 mutex_exit(&glvc_vsc_users_mutex); 277 return (DDI_FAILURE); 278 } else { 279 glvc_vsc_users++; 280 mutex_exit(&glvc_vsc_users_mutex); 281 } 282 283 DPRINTF(("Glvc instance %d negotiated VSC API version, " 284 " major 0x%lx minor 0x%lx\n", 285 instance, glvc_hsvc.hsvc_major, glvc_vsc_min_ver)); 286 287 if (ddi_soft_state_zalloc(glvc_ssp, instance) 288 != DDI_SUCCESS) { 289 mutex_enter(&glvc_vsc_users_mutex); 290 if (--glvc_vsc_users == 0) 291 (void) hsvc_unregister(&glvc_hsvc); 292 mutex_exit(&glvc_vsc_users_mutex); 293 return (DDI_FAILURE); 294 } 295 296 softsp = ddi_get_soft_state(glvc_ssp, instance); 297 298 /* Set the dip in the soft state */ 299 softsp->dip = dip; 300 301 softsp->open_state = GLVC_NO_OPEN; 302 softsp->send_complete_flag = 1; 303 304 glvc_debug = (uint64_t)ddi_getprop(DDI_DEV_T_ANY, 305 softsp->dip, DDI_PROP_DONTPASS, "glvc_debug", glvc_debug); 306 307 if ((softsp->s_id = (uint64_t)ddi_getprop(DDI_DEV_T_ANY, 308 softsp->dip, DDI_PROP_DONTPASS, "channel#", -1)) 309 == -1) { 310 cmn_err(CE_WARN, "Failed to get channel#"); 311 goto bad; 312 } 313 314 if ((softsp->mtu = (uint64_t)ddi_getprop(DDI_DEV_T_ANY, 315 softsp->dip, DDI_PROP_DONTPASS, "mtu", -1)) 316 <= 0) { 317 cmn_err(CE_WARN, "Failed to get mtu"); 318 goto bad; 319 } 320 321 softsp->mb_recv_buf = 322 (char *)kmem_zalloc(softsp->mtu, KM_NOSLEEP); 323 if (softsp->mb_recv_buf == NULL) { 324 cmn_err(CE_WARN, "Failed to alloc mem for recv buf"); 325 goto bad; 326 } 327 softsp->mb_recv_buf_pa = 328 va_to_pa((caddr_t)softsp->mb_recv_buf); 329 330 softsp->mb_send_buf = 331 (char *)kmem_zalloc(softsp->mtu, KM_NOSLEEP); 332 if (softsp->mb_send_buf == NULL) { 333 kmem_free(softsp->mb_recv_buf, softsp->mtu); 334 cmn_err(CE_WARN, "Failed to alloc mem for send buf"); 335 goto bad; 336 } 337 softsp->mb_send_buf_pa = 338 va_to_pa((caddr_t)softsp->mb_send_buf); 339 340 err = ddi_create_minor_node(dip, "glvc", S_IFCHR, 341 instance, DDI_PSEUDO, 0); 342 if (err != DDI_SUCCESS) { 343 kmem_free(softsp->mb_recv_buf, softsp->mtu); 344 kmem_free(softsp->mb_send_buf, softsp->mtu); 345 cmn_err(CE_WARN, "Failed to create minor node"); 346 goto bad; 347 } 348 349 mutex_init(&(softsp->open_mutex), NULL, MUTEX_DRIVER, NULL); 350 mutex_init(&(softsp->recv_mutex), NULL, MUTEX_DRIVER, NULL); 351 mutex_init(&(softsp->send_complete_mutex), NULL, 352 MUTEX_DRIVER, NULL); 353 mutex_init(&(softsp->statusreg_mutex), NULL, 354 MUTEX_DRIVER, NULL); 355 cv_init(&(softsp->recv_cv), NULL, CV_DRIVER, NULL); 356 cv_init(&(softsp->send_complete_cv), NULL, CV_DRIVER, NULL); 357 358 /* 359 * Add the handlers which watch for unsolicited messages 360 * and post event to Sysevent Framework. 361 */ 362 err = glvc_add_intr_handlers(dip); 363 if (err != DDI_SUCCESS) { 364 cmn_err(CE_WARN, "Failed to add intr handler"); 365 kmem_free(softsp->mb_recv_buf, softsp->mtu); 366 kmem_free(softsp->mb_send_buf, softsp->mtu); 367 ddi_remove_minor_node(dip, NULL); 368 goto bad1; 369 } 370 371 /* 372 * Trigger soft interrupt to start polling device if 373 * we are in the polling mode 374 */ 375 if (softsp->intr_mode == GLVC_POLLING_MODE) 376 ddi_trigger_softintr(softsp->poll_mode_softint_id); 377 378 ddi_report_dev(dip); 379 380 DPRINTF(("glvc instance %d, s_id %lu," 381 "mtu %lu attached\n", instance, softsp->s_id, 382 softsp->mtu)); 383 384 return (DDI_SUCCESS); 385 case DDI_RESUME: 386 return (DDI_SUCCESS); 387 default: 388 return (DDI_FAILURE); 389 } 390 391 bad1: 392 cv_destroy(&(softsp->send_complete_cv)); 393 cv_destroy(&(softsp->recv_cv)); 394 mutex_destroy(&(softsp->open_mutex)); 395 mutex_destroy(&(softsp->send_complete_mutex)); 396 mutex_destroy(&(softsp->recv_mutex)); 397 mutex_destroy(&(softsp->statusreg_mutex)); 398 399 bad: 400 mutex_enter(&glvc_vsc_users_mutex); 401 if (--glvc_vsc_users == 0) 402 (void) hsvc_unregister(&glvc_hsvc); 403 mutex_exit(&glvc_vsc_users_mutex); 404 cmn_err(CE_WARN, "glvc: attach failed for instance %d\n", instance); 405 ddi_soft_state_free(glvc_ssp, instance); 406 return (DDI_FAILURE); 407 } 408 409 410 static int 411 glvc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 412 { 413 int instance; 414 int err; 415 glvc_soft_state_t *softsp; 416 417 418 switch (cmd) { 419 case DDI_DETACH: 420 instance = ddi_get_instance(dip); 421 422 softsp = ddi_get_soft_state(glvc_ssp, instance); 423 424 cv_destroy(&(softsp->send_complete_cv)); 425 cv_destroy(&(softsp->recv_cv)); 426 mutex_destroy(&(softsp->open_mutex)); 427 mutex_destroy(&(softsp->statusreg_mutex)); 428 mutex_destroy(&(softsp->send_complete_mutex)); 429 mutex_destroy(&(softsp->recv_mutex)); 430 431 kmem_free(softsp->mb_recv_buf, softsp->mtu); 432 kmem_free(softsp->mb_send_buf, softsp->mtu); 433 434 err = glvc_remove_intr_handlers(dip); 435 436 if (err != DDI_SUCCESS) { 437 cmn_err(CE_WARN, "Failed to remove event handlers"); 438 return (DDI_FAILURE); 439 } 440 441 ddi_remove_minor_node(dip, NULL); 442 443 ddi_soft_state_free(glvc_ssp, instance); 444 445 mutex_enter(&glvc_vsc_users_mutex); 446 if (--glvc_vsc_users == 0) 447 (void) hsvc_unregister(&glvc_hsvc); 448 mutex_exit(&glvc_vsc_users_mutex); 449 450 return (DDI_SUCCESS); 451 case DDI_SUSPEND: 452 return (DDI_SUCCESS); 453 default: 454 return (DDI_FAILURE); 455 } 456 } 457 458 static int 459 glvc_add_intr_handlers(dev_info_t *dip) 460 { 461 int instance; 462 glvc_soft_state_t *softsp; 463 int err = DDI_FAILURE; 464 uint64_t polling_interval; 465 466 instance = ddi_get_instance(dip); 467 softsp = ddi_get_soft_state(glvc_ssp, instance); 468 469 if ((uint64_t)ddi_getprop(DDI_DEV_T_ANY, softsp->dip, 470 DDI_PROP_DONTPASS, "flags", -1) != -1) { 471 err = ddi_add_intr(dip, 0, NULL, NULL, glvc_intr, 472 (caddr_t)softsp); 473 if (err != DDI_SUCCESS) 474 cmn_err(CE_NOTE, "glvc, instance %d" 475 " ddi_add_intr() failed, using" 476 " polling mode", instance); 477 } 478 479 if (err == DDI_SUCCESS) { 480 softsp->intr_mode = GLVC_INTR_MODE; 481 polling_interval = (uint64_t)ddi_getprop(DDI_DEV_T_ANY, 482 softsp->dip, DDI_PROP_DONTPASS, "intrmode_poll", 483 GLVC_TIMEOUT_POLL); 484 DPRINTF(("glvc instance %d polling_interval = %lu\n", 485 instance, polling_interval)); 486 softsp->polling_interval = drv_usectohz(polling_interval); 487 } else { 488 DPRINTF(("glvc, instance %d intr support not found, " 489 "err = %d , use polling mode", instance, err)); 490 softsp->intr_mode = GLVC_POLLING_MODE; 491 polling_interval = 492 (uint64_t)ddi_getprop(DDI_DEV_T_ANY, 493 softsp->dip, DDI_PROP_DONTPASS, "pollmode_poll", 494 GLVC_POLLMODE_POLL); 495 DPRINTF(("glvc instance %d polling_interval = %lu\n", 496 instance, polling_interval)); 497 softsp->polling_interval = 498 drv_usectohz(polling_interval); 499 } 500 501 /* Now enable interrupt bits in the status register */ 502 if (softsp->intr_mode == GLVC_INTR_MODE) { 503 err = hv_service_setstatus(softsp->s_id, 504 GLVC_REG_RECV_ENA|GLVC_REG_SEND_ENA); 505 if (err != H_EOK) { 506 cmn_err(CE_NOTE, "glvc instance %d" 507 " cannot enable receive interrupt\n", 508 instance); 509 return (DDI_FAILURE); 510 } 511 } 512 513 514 err = ddi_add_softintr(dip, DDI_SOFTINT_LOW, 515 &softsp->poll_mode_softint_id, NULL, NULL, 516 glvc_soft_intr, (caddr_t)softsp); 517 518 return (err); 519 } 520 521 static int 522 glvc_remove_intr_handlers(dev_info_t *dip) 523 { 524 int instance; 525 glvc_soft_state_t *softsp; 526 527 instance = ddi_get_instance(dip); 528 softsp = ddi_get_soft_state(glvc_ssp, instance); 529 530 if (softsp->intr_mode == GLVC_INTR_MODE) 531 ddi_remove_intr(dip, 0, NULL); 532 533 ddi_remove_softintr(softsp->poll_mode_softint_id); 534 535 softsp->intr_mode = GLVC_MODE_NONE; 536 softsp->polling_interval = 0; 537 538 return (DDI_SUCCESS); 539 } 540 541 static uint_t 542 glvc_soft_intr(caddr_t arg) 543 { 544 /* 545 * Call the interrupt handle routine to check the register 546 * status. 547 */ 548 (uint_t)glvc_intr(arg); 549 550 return (DDI_INTR_CLAIMED); 551 } 552 553 /*ARGSUSED*/ 554 static int 555 glvc_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p) 556 { 557 int error = 0; 558 int instance; 559 glvc_soft_state_t *softsp; 560 561 instance = getminor(*dev_p); 562 563 softsp = ddi_get_soft_state(glvc_ssp, instance); 564 565 mutex_enter(&softsp->open_mutex); 566 567 switch (softsp->open_state) { 568 case GLVC_NO_OPEN: 569 if (flag & FEXCL) 570 softsp->open_state = GLVC_EXCL_OPEN; 571 else 572 softsp->open_state = GLVC_OPEN; 573 break; 574 575 case GLVC_OPEN: 576 if (flag & FEXCL) 577 error = EBUSY; 578 break; 579 580 case GLVC_EXCL_OPEN: 581 error = EBUSY; 582 break; 583 584 default: 585 /* Should not happen */ 586 cmn_err(CE_WARN, "glvc_open: bad open state %d.", 587 softsp->open_state); 588 error = ENXIO; 589 break; 590 } 591 592 mutex_exit(&softsp->open_mutex); 593 594 return (error); 595 } 596 597 /*ARGSUSED*/ 598 static int 599 glvc_close(dev_t dev, int flag, int otyp, cred_t *cred_p) 600 { 601 glvc_soft_state_t *softsp; 602 int instance; 603 int error = 0; 604 605 instance = getminor(dev); 606 607 softsp = ddi_get_soft_state(glvc_ssp, instance); 608 609 mutex_enter(&softsp->open_mutex); 610 if (softsp->open_state == GLVC_NO_OPEN) { 611 cmn_err(CE_WARN, 612 "glvc_close: device already closed"); 613 error = ENXIO; 614 } else { 615 softsp->open_state = GLVC_NO_OPEN; 616 } 617 mutex_exit(&softsp->open_mutex); 618 619 return (error); 620 } 621 622 /*ARGSUSED*/ 623 static int 624 glvc_read(dev_t dev, struct uio *uiop, cred_t *credp) 625 { 626 glvc_soft_state_t *softsp; 627 int instance; 628 int rv, error = DDI_SUCCESS; 629 uint64_t hverr, recv_count = 0; 630 uint64_t status_reg; 631 632 instance = getminor(dev); 633 634 softsp = ddi_get_soft_state(glvc_ssp, instance); 635 636 mutex_enter(&softsp->recv_mutex); 637 638 hverr = hv_service_getstatus(softsp->s_id, &status_reg); 639 DPRINTF(("glvc_read: err = %ld, getstatus = 0x%lx", 640 hverr, status_reg)); 641 642 643 /* 644 * If no data available, we wait till we get some. 645 * Notice we still holding the recv_mutex lock at this 646 * point. 647 */ 648 while (hverr == H_EOK && (status_reg & GLVC_REG_RECV) != 649 GLVC_REG_RECV) { 650 rv = cv_reltimedwait_sig(&softsp->recv_cv, 651 &softsp->recv_mutex, softsp->polling_interval, 652 TR_CLOCK_TICK); 653 if (rv == 0) { 654 /* 655 * We got interrupted. 656 */ 657 mutex_exit(&softsp->recv_mutex); 658 return (EINTR); 659 } 660 if (rv == -1) { 661 /* 662 * Timeout wait, trigger a soft intr in case 663 * we miss an interrupt or in polling mode. 664 */ 665 ddi_trigger_softintr(softsp->poll_mode_softint_id); 666 } 667 hverr = hv_service_getstatus(softsp->s_id, &status_reg); 668 DPRINTF(("glvc_read: err = %ld, getstatus = 0x%lx", 669 hverr, status_reg)); 670 } 671 672 /* Read data into kernel buffer */ 673 hverr = hv_service_recv(softsp->s_id, softsp->mb_recv_buf_pa, 674 softsp->mtu, &recv_count); 675 676 DPRINTF(("Instance %d glvc_read returns error = %ld, recv_count = %lu", 677 instance, hverr, recv_count)); 678 679 if (hverr == H_EOK) { 680 if (uiop->uio_resid < recv_count) { 681 DPRINTF(("Instance %d, glvc_read user buffer " 682 "size(%lu) smaller than number of bytes " 683 "received(%lu).", instance, uiop->uio_resid, 684 recv_count)); 685 mutex_exit(&softsp->recv_mutex); 686 return (EINVAL); 687 } 688 /* move data from kernel to user space */ 689 error = uiomove(softsp->mb_recv_buf, recv_count, 690 UIO_READ, uiop); 691 } else { 692 error = glvc_emap_h2s(hverr); 693 } 694 695 /* Clear the RECV data interrupt bit on device register */ 696 if (hv_service_clrstatus(softsp->s_id, GLVC_REG_RECV) != H_EOK) { 697 cmn_err(CE_WARN, "glvc_read clear status reg failed"); 698 } 699 700 /* Set RECV interrupt enable bit so we can receive interrupt */ 701 if (softsp->intr_mode == GLVC_INTR_MODE) 702 if (hv_service_setstatus(softsp->s_id, GLVC_REG_RECV_ENA) 703 != H_EOK) { 704 cmn_err(CE_WARN, "glvc_read set status reg failed"); 705 } 706 707 mutex_exit(&softsp->recv_mutex); 708 709 return (error); 710 } 711 712 /*ARGSUSED*/ 713 static int 714 glvc_write(dev_t dev, struct uio *uiop, cred_t *credp) 715 { 716 glvc_soft_state_t *softsp; 717 int instance; 718 int rv, error = DDI_SUCCESS; 719 uint64_t hverr, send_count = 0; 720 721 instance = getminor(dev); 722 723 softsp = ddi_get_soft_state(glvc_ssp, instance); 724 725 if (uiop->uio_resid > softsp->mtu) 726 return (EINVAL); 727 728 send_count = uiop->uio_resid; 729 DPRINTF(("instance %d glvc_write: request to send %lu bytes", 730 instance, send_count)); 731 732 mutex_enter(&softsp->send_complete_mutex); 733 while (softsp->send_complete_flag == 0) { 734 rv = cv_reltimedwait_sig(&softsp->send_complete_cv, 735 &softsp->send_complete_mutex, softsp->polling_interval, 736 TR_CLOCK_TICK); 737 if (rv == 0) { 738 /* 739 * We got interrupted. 740 */ 741 mutex_exit(&softsp->send_complete_mutex); 742 return (EINTR); 743 } 744 if (rv == -1) { 745 /* 746 * Timeout wait, trigger a soft intr in case 747 * we miss an interrupt or in polling mode. 748 */ 749 ddi_trigger_softintr(softsp->poll_mode_softint_id); 750 } 751 } 752 753 /* move data from to user to kernel space */ 754 error = uiomove(softsp->mb_send_buf, send_count, 755 UIO_WRITE, uiop); 756 757 if (error == 0) { 758 hverr = hv_service_send(softsp->s_id, 759 softsp->mb_send_buf_pa, send_count, &send_count); 760 error = glvc_emap_h2s(hverr); 761 } 762 763 DPRINTF(("instance %d glvc_write write check error = %d," 764 " send_count = %lu", instance, error, send_count)); 765 766 softsp->send_complete_flag = 0; 767 768 mutex_exit(&softsp->send_complete_mutex); 769 770 return (error); 771 } 772 773 /* 774 * Interrupt handler 775 */ 776 static uint_t 777 glvc_intr(caddr_t arg) 778 { 779 glvc_soft_state_t *softsp = (glvc_soft_state_t *)arg; 780 uint64_t status_reg; 781 int error = DDI_INTR_UNCLAIMED; 782 uint64_t hverr = H_EOK; 783 uint64_t clr_bits = 0; 784 785 mutex_enter(&softsp->recv_mutex); 786 mutex_enter(&softsp->send_complete_mutex); 787 hverr = hv_service_getstatus(softsp->s_id, &status_reg); 788 DPRINTF(("glvc_intr: err = %ld, getstatus = 0x%lx", 789 hverr, status_reg)); 790 791 /* 792 * Clear SEND_COMPLETE bit and disable RECV interrupt 793 */ 794 if (status_reg & GLVC_REG_SEND) 795 clr_bits |= GLVC_REG_SEND; 796 if ((softsp->intr_mode == GLVC_INTR_MODE) && 797 (status_reg & GLVC_REG_RECV)) 798 clr_bits |= GLVC_REG_RECV_ENA; 799 800 if ((hverr = hv_service_clrstatus(softsp->s_id, clr_bits)) 801 != H_EOK) { 802 cmn_err(CE_WARN, "glvc_intr clear status reg failed" 803 "error = %ld", hverr); 804 mutex_exit(&softsp->send_complete_mutex); 805 mutex_exit(&softsp->recv_mutex); 806 return (DDI_INTR_UNCLAIMED); 807 } 808 809 if (status_reg & GLVC_REG_RECV) { 810 cv_broadcast(&softsp->recv_cv); 811 error = DDI_INTR_CLAIMED; 812 } 813 814 if (status_reg & GLVC_REG_SEND) { 815 softsp->send_complete_flag = 1; 816 cv_broadcast(&softsp->send_complete_cv); 817 error = DDI_INTR_CLAIMED; 818 } 819 820 mutex_exit(&softsp->send_complete_mutex); 821 mutex_exit(&softsp->recv_mutex); 822 823 return (error); 824 } 825 826 /* 827 * Peek to see if there is data received. If no data available, 828 * we sleep wait. If there is data, read from hypervisor and copy 829 * to ioctl buffer. We don't clear the receive data interrupt bit. 830 */ 831 static int 832 glvc_peek(glvc_soft_state_t *softsp, glvc_xport_msg_peek_t *msg_peek) 833 { 834 int rv, error = 0; 835 uint64_t hverr = H_EOK; 836 uint64_t recv_count = 0; 837 uint64_t status_reg; 838 839 mutex_enter(&softsp->recv_mutex); 840 841 hverr = hv_service_getstatus(softsp->s_id, &status_reg); 842 DPRINTF(("glvc_peek: err = %ld, getstatus = 0x%lx", 843 hverr, status_reg)); 844 845 /* 846 * If no data available, we wait till we get some. 847 * Notice we still holding the recv_mutex lock at 848 * this point. 849 */ 850 while (hverr == H_EOK && (status_reg & GLVC_REG_RECV) != 851 GLVC_REG_RECV) { 852 rv = cv_reltimedwait_sig(&softsp->recv_cv, 853 &softsp->recv_mutex, softsp->polling_interval, 854 TR_CLOCK_TICK); 855 if (rv == 0) { 856 /* 857 * We got interrupted. 858 */ 859 mutex_exit(&softsp->recv_mutex); 860 return (EINTR); 861 } 862 if (rv == -1) { 863 /* 864 * Timeout wait, trigger a soft intr in case 865 * we miss an interrupt or in polling mode. 866 */ 867 ddi_trigger_softintr(softsp->poll_mode_softint_id); 868 } 869 hverr = hv_service_getstatus(softsp->s_id, &status_reg); 870 DPRINTF(("glvc_peek: err = %ld, getstatus = 0x%lx", 871 hverr, status_reg)); 872 } 873 874 /* Read data into kernel buffer */ 875 hverr = hv_service_recv(softsp->s_id, softsp->mb_recv_buf_pa, 876 softsp->mtu, &recv_count); 877 DPRINTF(("glvc_peek recv data, error = %ld, recv_count = %lu", 878 hverr, recv_count)); 879 880 if (hverr == H_EOK && recv_count > 0) { 881 (void *) memcpy(msg_peek->buf, 882 softsp->mb_recv_buf, recv_count); 883 msg_peek->buflen = recv_count; 884 } else { 885 error = glvc_emap_h2s(hverr); 886 } 887 888 mutex_exit(&softsp->recv_mutex); 889 890 return (error); 891 } 892 893 static int 894 glvc_ioctl_opt_op(glvc_soft_state_t *softsp, intptr_t arg, int mode) 895 { 896 glvc_xport_opt_op_t glvc_xport_cmd; 897 uint64_t status_reg; 898 int retval = 0; 899 uint64_t hverr; 900 901 if (ddi_copyin((caddr_t)arg, (caddr_t)&glvc_xport_cmd, 902 sizeof (glvc_xport_opt_op_t), mode) != 0) { 903 return (EFAULT); 904 } 905 906 switch (glvc_xport_cmd.opt_sel) { 907 case GLVC_XPORT_OPT_MTU_SZ: 908 if (glvc_xport_cmd.op_sel == GLVC_XPORT_OPT_GET) { 909 glvc_xport_cmd.opt_val = softsp->mtu; 910 retval = ddi_copyout((caddr_t)&glvc_xport_cmd, 911 (caddr_t)arg, sizeof (glvc_xport_opt_op_t), 912 mode); 913 } else 914 retval = ENOTSUP; 915 916 break; 917 918 case GLVC_XPORT_OPT_REG_STATUS: 919 if (glvc_xport_cmd.op_sel == GLVC_XPORT_OPT_GET) { 920 mutex_enter(&softsp->statusreg_mutex); 921 hverr = hv_service_getstatus(softsp->s_id, &status_reg); 922 mutex_exit(&softsp->statusreg_mutex); 923 if (hverr == H_EOK) { 924 glvc_xport_cmd.opt_val = (uint32_t)status_reg; 925 retval = ddi_copyout((caddr_t)&glvc_xport_cmd, 926 (caddr_t)arg, sizeof (glvc_xport_opt_op_t), 927 mode); 928 } else { 929 retval = EIO; 930 } 931 } else { 932 retval = ENOTSUP; 933 } 934 935 break; 936 937 default: 938 retval = ENOTSUP; 939 break; 940 } 941 942 return (retval); 943 } 944 945 946 /*ARGSUSED*/ 947 static int 948 glvc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p, 949 int *rval_p) 950 { 951 glvc_soft_state_t *softsp; 952 int instance = getminor(dev); 953 glvc_xport_msg_peek_t glvc_peek_msg, msg_peek_cmd; 954 glvc_xport_msg_peek32_t msg_peek_cmd32; 955 956 int retval = 0; 957 958 softsp = ddi_get_soft_state(glvc_ssp, instance); 959 960 switch (cmd) { 961 case GLVC_XPORT_IOCTL_OPT_OP: 962 retval = glvc_ioctl_opt_op(softsp, arg, mode); 963 break; 964 965 case GLVC_XPORT_IOCTL_DATA_PEEK: 966 glvc_peek_msg.buf = 967 (char *)kmem_zalloc(softsp->mtu, KM_NOSLEEP); 968 if (glvc_peek_msg.buf == NULL) 969 return (EBUSY); 970 retval = glvc_peek(softsp, &glvc_peek_msg); 971 if (retval == 0) { 972 switch (ddi_model_convert_from(mode)) { 973 case DDI_MODEL_ILP32: 974 if (ddi_copyin((caddr_t)arg, 975 (caddr_t)&msg_peek_cmd32, 976 sizeof (glvc_xport_msg_peek32_t), 977 mode) == -1) { 978 retval = EFAULT; 979 break; 980 } 981 982 if (msg_peek_cmd32.buflen32 == 0) { 983 retval = EINVAL; 984 break; 985 } 986 987 if (msg_peek_cmd32.buflen32 > 988 glvc_peek_msg.buflen) 989 msg_peek_cmd32.buflen32 = 990 glvc_peek_msg.buflen; 991 992 if (ddi_copyout((caddr_t)glvc_peek_msg.buf, 993 (caddr_t)(uintptr_t)msg_peek_cmd32.buf32, 994 msg_peek_cmd32.buflen32, mode) == -1) { 995 retval = EFAULT; 996 break; 997 } 998 999 if (ddi_copyout((caddr_t)&msg_peek_cmd32, 1000 (caddr_t)arg, 1001 sizeof (glvc_xport_msg_peek32_t), mode) 1002 == -1) 1003 retval = EFAULT; 1004 break; 1005 1006 case DDI_MODEL_NONE: 1007 if (ddi_copyin((caddr_t)arg, 1008 (caddr_t)&msg_peek_cmd, 1009 sizeof (glvc_xport_msg_peek_t), mode) == -1) 1010 retval = EFAULT; 1011 1012 if (msg_peek_cmd.buflen == 0) { 1013 retval = EINVAL; 1014 break; 1015 } 1016 1017 if (msg_peek_cmd.buflen > glvc_peek_msg.buflen) 1018 msg_peek_cmd.buflen = 1019 glvc_peek_msg.buflen; 1020 1021 if (ddi_copyout((caddr_t)glvc_peek_msg.buf, 1022 (caddr_t)msg_peek_cmd.buf, 1023 msg_peek_cmd.buflen, mode) == -1) { 1024 retval = EFAULT; 1025 break; 1026 } 1027 1028 if (ddi_copyout((caddr_t)&msg_peek_cmd, 1029 (caddr_t)arg, 1030 sizeof (glvc_xport_msg_peek_t), mode) == -1) 1031 retval = EFAULT; 1032 break; 1033 1034 default: 1035 retval = EFAULT; 1036 break; 1037 } 1038 } 1039 kmem_free(glvc_peek_msg.buf, softsp->mtu); 1040 break; 1041 1042 default: 1043 retval = ENOTSUP; 1044 break; 1045 } 1046 return (retval); 1047 } 1048 1049 /* 1050 * Map hypervisor error code to solaris. Only 1051 * H_EOK, H_EINVA, H_EWOULDBLOCK and H_EIO are meaningful 1052 * to this device. All other error codes are mapped to EIO. 1053 */ 1054 static int 1055 glvc_emap_h2s(uint64_t hv_errcode) 1056 { 1057 int s_errcode; 1058 1059 switch (hv_errcode) { 1060 case H_EOK: 1061 s_errcode = 0; 1062 break; 1063 1064 case H_EINVAL: 1065 s_errcode = EINVAL; 1066 break; 1067 1068 case H_EWOULDBLOCK: 1069 s_errcode = EWOULDBLOCK; 1070 break; 1071 1072 case H_EIO: 1073 s_errcode = EIO; 1074 break; 1075 1076 default: 1077 /* should not happen */ 1078 DPRINTF(("Unexpected device error code %ld received, " 1079 "mapped to EIO", hv_errcode)); 1080 s_errcode = EIO; 1081 break; 1082 } 1083 1084 return (s_errcode); 1085 } 1086