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 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * xenbus_dev.c 29 * 30 * Driver giving user-space access to the kernel's xenbus connection 31 * to xenstore. 32 * 33 * Copyright (c) 2005, Christian Limpach 34 * Copyright (c) 2005, Rusty Russell, IBM Corporation 35 * 36 * This file may be distributed separately from the Linux kernel, or 37 * incorporated into other software packages, subject to the following license: 38 * 39 * Permission is hereby granted, free of charge, to any person obtaining a copy 40 * of this source file (the "Software"), to deal in the Software without 41 * restriction, including without limitation the rights to use, copy, modify, 42 * merge, publish, distribute, sublicense, and/or sell copies of the Software, 43 * and to permit persons to whom the Software is furnished to do so, subject to 44 * the following conditions: 45 * 46 * The above copyright notice and this permission notice shall be included in 47 * all copies or substantial portions of the Software. 48 * 49 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 50 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 51 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 52 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 53 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 54 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 55 * IN THE SOFTWARE. 56 */ 57 58 #pragma ident "%Z%%M% %I% %E% SMI" 59 60 #include <sys/types.h> 61 #include <sys/sysmacros.h> 62 #include <sys/conf.h> 63 #include <sys/stat.h> 64 #include <sys/modctl.h> 65 #include <sys/uio.h> 66 #include <sys/list.h> 67 #include <sys/file.h> 68 #include <sys/errno.h> 69 #include <sys/open.h> 70 #include <sys/cred.h> 71 #include <sys/condvar.h> 72 #include <sys/ddi.h> 73 #include <sys/sunddi.h> 74 #ifdef XPV_HVM_DRIVER 75 #include <public/io/xenbus.h> 76 #include <public/io/xs_wire.h> 77 #include <sys/xpv_support.h> 78 #endif 79 #include <sys/hypervisor.h> 80 #include <xen/sys/xenbus.h> 81 #include <xen/sys/xenbus_comms.h> 82 #include <xen/sys/xenbus_impl.h> 83 #include <xen/public/io/xs_wire.h> 84 85 #ifdef DEBUG 86 #define XENBUSDRV_DBPRINT(fmt) { if (xenbusdrv_debug) cmn_err fmt; } 87 #else 88 #define XENBUSDRV_DBPRINT(fmt) 89 #endif /* ifdef DEBUG */ 90 91 /* Some handy macros */ 92 #define XENBUSDRV_MASK_READ_IDX(idx) ((idx) & (PAGESIZE - 1)) 93 #define XENBUSDRV_MINOR2INST(minor) ((int)(minor)) 94 #define XENBUSDRV_NCLONES 256 95 #define XENBUSDRV_INST2SOFTS(instance) \ 96 ((xenbus_dev_t *)ddi_get_soft_state(xenbusdrv_statep, (instance))) 97 98 static int xenbusdrv_debug = 0; 99 static int xenbusdrv_clone_tab[XENBUSDRV_NCLONES]; 100 static dev_info_t *xenbusdrv_dip; 101 static kmutex_t xenbusdrv_clone_tab_mutex; 102 103 struct xenbus_dev_transaction { 104 list_t list; 105 xenbus_transaction_t handle; 106 }; 107 108 /* Soft state data structure for xenbus driver */ 109 struct xenbus_dev_data { 110 dev_info_t *dip; 111 112 /* In-progress transaction. */ 113 list_t transactions; 114 115 /* Partial request. */ 116 unsigned int len; 117 union { 118 struct xsd_sockmsg msg; 119 char buffer[MMU_PAGESIZE]; 120 } u; 121 122 /* Response queue. */ 123 char read_buffer[MMU_PAGESIZE]; 124 unsigned int read_cons, read_prod; 125 kcondvar_t read_cv; 126 kmutex_t read_mutex; 127 int xenstore_inst; 128 }; 129 typedef struct xenbus_dev_data xenbus_dev_t; 130 static void *xenbusdrv_statep; 131 132 static int xenbusdrv_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 133 static int xenbusdrv_attach(dev_info_t *, ddi_attach_cmd_t); 134 static int xenbusdrv_detach(dev_info_t *, ddi_detach_cmd_t); 135 static int xenbusdrv_open(dev_t *, int, int, cred_t *); 136 static int xenbusdrv_close(dev_t, int, int, cred_t *); 137 static int xenbusdrv_read(dev_t, struct uio *, cred_t *); 138 static int xenbusdrv_write(dev_t, struct uio *, cred_t *); 139 static int xenbusdrv_devmap(dev_t, devmap_cookie_t, offset_t, size_t, size_t *, 140 uint_t); 141 static int xenbusdrv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 142 static int xenbusdrv_queue_reply(xenbus_dev_t *, const struct xsd_sockmsg *, 143 const char *); 144 145 /* Solaris driver framework */ 146 147 static struct cb_ops xenbusdrv_cb_ops = { 148 xenbusdrv_open, /* cb_open */ 149 xenbusdrv_close, /* cb_close */ 150 nodev, /* cb_strategy */ 151 nodev, /* cb_print */ 152 nodev, /* cb_dump */ 153 xenbusdrv_read, /* cb_read */ 154 xenbusdrv_write, /* cb_write */ 155 xenbusdrv_ioctl, /* cb_ioctl */ 156 xenbusdrv_devmap, /* cb_devmap */ 157 NULL, /* cb_mmap */ 158 NULL, /* cb_segmap */ 159 nochpoll, /* cb_chpoll */ 160 ddi_prop_op, /* cb_prop_op */ 161 0, /* cb_stream */ 162 D_DEVMAP | D_NEW | D_MP, /* cb_flag */ 163 CB_REV 164 }; 165 166 static struct dev_ops xenbusdrv_dev_ops = { 167 DEVO_REV, /* devo_rev */ 168 0, /* devo_refcnt */ 169 xenbusdrv_info, /* devo_getinfo */ 170 nulldev, /* devo_identify */ 171 nulldev, /* devo_probe */ 172 xenbusdrv_attach, /* devo_attach */ 173 xenbusdrv_detach, /* devo_detach */ 174 nodev, /* devo_reset */ 175 &xenbusdrv_cb_ops, /* devo_cb_ops */ 176 NULL, /* devo_bus_ops */ 177 NULL /* power */ 178 }; 179 180 static struct modldrv modldrv = { 181 &mod_driverops, /* Type of module. This one is a driver */ 182 "virtual bus driver v%I%", /* Name of the module. */ 183 &xenbusdrv_dev_ops /* driver ops */ 184 }; 185 186 static struct modlinkage modlinkage = { 187 MODREV_1, 188 &modldrv, 189 NULL 190 }; 191 192 int 193 _init(void) 194 { 195 int e; 196 197 e = ddi_soft_state_init(&xenbusdrv_statep, sizeof (xenbus_dev_t), 1); 198 if (e) 199 return (e); 200 201 e = mod_install(&modlinkage); 202 if (e) 203 ddi_soft_state_fini(&xenbusdrv_statep); 204 205 return (e); 206 } 207 208 int 209 _fini(void) 210 { 211 int e; 212 213 e = mod_remove(&modlinkage); 214 if (e) 215 return (e); 216 217 ddi_soft_state_fini(&xenbusdrv_statep); 218 219 return (0); 220 } 221 222 int 223 _info(struct modinfo *modinfop) 224 { 225 return (mod_info(&modlinkage, modinfop)); 226 } 227 228 /* ARGSUSED */ 229 static int 230 xenbusdrv_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 231 { 232 dev_t dev = (dev_t)arg; 233 minor_t minor = getminor(dev); 234 int retval; 235 236 switch (cmd) { 237 case DDI_INFO_DEVT2DEVINFO: 238 if (minor != 0 || xenbusdrv_dip == NULL) { 239 *result = (void *)NULL; 240 retval = DDI_FAILURE; 241 } else { 242 *result = (void *)xenbusdrv_dip; 243 retval = DDI_SUCCESS; 244 } 245 break; 246 case DDI_INFO_DEVT2INSTANCE: 247 *result = (void *)0; 248 retval = DDI_SUCCESS; 249 break; 250 default: 251 retval = DDI_FAILURE; 252 } 253 return (retval); 254 } 255 256 static int 257 xenbusdrv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 258 { 259 int error; 260 int unit = ddi_get_instance(dip); 261 262 263 switch (cmd) { 264 case DDI_ATTACH: 265 break; 266 case DDI_RESUME: 267 return (DDI_SUCCESS); 268 default: 269 cmn_err(CE_WARN, "xenbus_attach: unknown cmd 0x%x\n", cmd); 270 return (DDI_FAILURE); 271 } 272 273 /* DDI_ATTACH */ 274 275 /* 276 * only one instance - but we clone using the open routine 277 */ 278 if (ddi_get_instance(dip) > 0) 279 return (DDI_FAILURE); 280 281 mutex_init(&xenbusdrv_clone_tab_mutex, NULL, MUTEX_DRIVER, 282 NULL); 283 284 error = ddi_create_minor_node(dip, "xenbus", S_IFCHR, unit, 285 DDI_PSEUDO, NULL); 286 if (error != DDI_SUCCESS) 287 goto fail; 288 289 /* 290 * save dip for getinfo 291 */ 292 xenbusdrv_dip = dip; 293 ddi_report_dev(dip); 294 295 #ifndef XPV_HVM_DRIVER 296 if (DOMAIN_IS_INITDOMAIN(xen_info)) 297 xs_dom0_init(); 298 #endif 299 300 return (DDI_SUCCESS); 301 302 fail: 303 (void) xenbusdrv_detach(dip, DDI_DETACH); 304 return (error); 305 } 306 307 static int 308 xenbusdrv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 309 { 310 /* 311 * again, only one instance 312 */ 313 if (ddi_get_instance(dip) > 0) 314 return (DDI_FAILURE); 315 316 switch (cmd) { 317 case DDI_DETACH: 318 ddi_remove_minor_node(dip, NULL); 319 mutex_destroy(&xenbusdrv_clone_tab_mutex); 320 xenbusdrv_dip = NULL; 321 return (DDI_SUCCESS); 322 case DDI_SUSPEND: 323 return (DDI_SUCCESS); 324 default: 325 cmn_err(CE_WARN, "xenbus_detach: unknown cmd 0x%x\n", cmd); 326 return (DDI_FAILURE); 327 } 328 } 329 330 /* ARGSUSED */ 331 static int 332 xenbusdrv_open(dev_t *devp, int flag, int otyp, cred_t *credp) 333 { 334 xenbus_dev_t *xbs; 335 minor_t minor = getminor(*devp); 336 337 if (otyp == OTYP_BLK) 338 return (ENXIO); 339 340 /* 341 * only allow open on minor = 0 - the clone device 342 */ 343 if (minor != 0) 344 return (ENXIO); 345 346 /* 347 * find a free slot and grab it 348 */ 349 mutex_enter(&xenbusdrv_clone_tab_mutex); 350 for (minor = 1; minor < XENBUSDRV_NCLONES; minor++) { 351 if (xenbusdrv_clone_tab[minor] == 0) { 352 xenbusdrv_clone_tab[minor] = 1; 353 break; 354 } 355 } 356 mutex_exit(&xenbusdrv_clone_tab_mutex); 357 if (minor == XENBUSDRV_NCLONES) 358 return (EAGAIN); 359 360 /* Allocate softstate structure */ 361 if (ddi_soft_state_zalloc(xenbusdrv_statep, 362 XENBUSDRV_MINOR2INST(minor)) != DDI_SUCCESS) { 363 mutex_enter(&xenbusdrv_clone_tab_mutex); 364 xenbusdrv_clone_tab[minor] = 0; 365 mutex_exit(&xenbusdrv_clone_tab_mutex); 366 return (EAGAIN); 367 } 368 xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(minor)); 369 370 /* ... and init it */ 371 xbs->dip = xenbusdrv_dip; 372 mutex_init(&xbs->read_mutex, NULL, MUTEX_DRIVER, NULL); 373 cv_init(&xbs->read_cv, NULL, CV_DEFAULT, NULL); 374 list_create(&xbs->transactions, sizeof (struct xenbus_dev_transaction), 375 offsetof(struct xenbus_dev_transaction, list)); 376 377 /* clone driver */ 378 *devp = makedevice(getmajor(*devp), minor); 379 XENBUSDRV_DBPRINT((CE_NOTE, "Xenbus drv open succeeded, minor=%d", 380 minor)); 381 382 return (0); 383 } 384 385 /* ARGSUSED */ 386 static int 387 xenbusdrv_close(dev_t dev, int flag, int otyp, struct cred *credp) 388 { 389 xenbus_dev_t *xbs; 390 minor_t minor = getminor(dev); 391 struct xenbus_dev_transaction *trans; 392 393 xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(minor)); 394 if (xbs == NULL) 395 return (ENXIO); 396 397 #ifdef notyet 398 /* 399 * XXPV - would like to be able to notify xenstore down here, but 400 * as the daemon is currently written, it doesn't leave the device 401 * open after initial setup, so we have no way of knowing if it has 402 * gone away. 403 */ 404 if (xbs->xenstore_inst) 405 xs_notify_xenstore_down(); 406 #endif 407 /* free pending transaction */ 408 while (trans = (struct xenbus_dev_transaction *) 409 list_head(&xbs->transactions)) { 410 (void) xenbus_transaction_end(trans->handle, 1); 411 list_remove(&xbs->transactions, (void *)trans); 412 kmem_free(trans, sizeof (*trans)); 413 } 414 415 mutex_destroy(&xbs->read_mutex); 416 cv_destroy(&xbs->read_cv); 417 ddi_soft_state_free(xenbusdrv_statep, XENBUSDRV_MINOR2INST(minor)); 418 419 /* 420 * free clone tab slot 421 */ 422 mutex_enter(&xenbusdrv_clone_tab_mutex); 423 xenbusdrv_clone_tab[minor] = 0; 424 mutex_exit(&xenbusdrv_clone_tab_mutex); 425 426 XENBUSDRV_DBPRINT((CE_NOTE, "Xenbus drv close succeeded, minor=%d", 427 minor)); 428 429 return (0); 430 } 431 432 /* ARGSUSED */ 433 static int 434 xenbusdrv_read(dev_t dev, struct uio *uiop, cred_t *credp) 435 { 436 xenbus_dev_t *xbs; 437 size_t len; 438 int res, ret; 439 int idx; 440 441 XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_read called")); 442 443 xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev))); 444 445 mutex_enter(&xbs->read_mutex); 446 447 /* check if we have something to read */ 448 while (xbs->read_prod == xbs->read_cons) { 449 if (cv_wait_sig(&xbs->read_cv, &xbs->read_mutex) == 0) { 450 mutex_exit(&xbs->read_mutex); 451 return (EINTR); 452 } 453 } 454 455 idx = XENBUSDRV_MASK_READ_IDX(xbs->read_cons); 456 res = uiop->uio_resid; 457 458 len = xbs->read_prod - xbs->read_cons; 459 460 if (len > (sizeof (xbs->read_buffer) - idx)) 461 len = sizeof (xbs->read_buffer) - idx; 462 if (len > res) 463 len = res; 464 465 ret = uiomove(xbs->read_buffer + idx, len, UIO_READ, uiop); 466 xbs->read_cons += res - uiop->uio_resid; 467 mutex_exit(&xbs->read_mutex); 468 469 return (ret); 470 } 471 472 /* 473 * prepare data for xenbusdrv_read() 474 */ 475 static int 476 xenbusdrv_queue_reply(xenbus_dev_t *xbs, const struct xsd_sockmsg *msg, 477 const char *reply) 478 { 479 int i; 480 int remaining; 481 482 XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_queue_reply called")); 483 484 mutex_enter(&xbs->read_mutex); 485 486 remaining = sizeof (xbs->read_buffer) - 487 (xbs->read_prod - xbs->read_cons); 488 489 if (sizeof (*msg) + msg->len > remaining) { 490 mutex_exit(&xbs->read_mutex); 491 return (EOVERFLOW); 492 } 493 494 for (i = 0; i < sizeof (*msg); i++, xbs->read_prod++) { 495 xbs->read_buffer[XENBUSDRV_MASK_READ_IDX(xbs->read_prod)] = 496 ((char *)msg)[i]; 497 } 498 499 for (i = 0; i < msg->len; i++, xbs->read_prod++) { 500 xbs->read_buffer[XENBUSDRV_MASK_READ_IDX(xbs->read_prod)] = 501 reply[i]; 502 } 503 504 cv_broadcast(&xbs->read_cv); 505 506 mutex_exit(&xbs->read_mutex); 507 508 XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_queue_reply exited")); 509 510 return (0); 511 } 512 513 /* ARGSUSED */ 514 static int 515 xenbusdrv_write(dev_t dev, struct uio *uiop, cred_t *credp) 516 { 517 xenbus_dev_t *xbs; 518 struct xenbus_dev_transaction *trans; 519 void *reply; 520 size_t len; 521 int rc = 0; 522 523 XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_write called")); 524 525 xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev))); 526 len = uiop->uio_resid; 527 528 if ((len + xbs->len) > sizeof (xbs->u.buffer)) { 529 XENBUSDRV_DBPRINT((CE_WARN, "Request is too big")); 530 rc = EINVAL; 531 goto out; 532 } 533 534 if (uiomove(xbs->u.buffer + xbs->len, len, UIO_WRITE, uiop) != 0) { 535 XENBUSDRV_DBPRINT((CE_WARN, "Uiomove failed")); 536 rc = EFAULT; 537 goto out; 538 } 539 540 xbs->len += len; 541 542 if (xbs->len < (sizeof (xbs->u.msg)) || 543 xbs->len < (sizeof (xbs->u.msg) + xbs->u.msg.len)) { 544 XENBUSDRV_DBPRINT((CE_NOTE, "Partial request")); 545 return (0); 546 } 547 548 switch (xbs->u.msg.type) { 549 case XS_TRANSACTION_START: 550 case XS_TRANSACTION_END: 551 case XS_DIRECTORY: 552 case XS_READ: 553 case XS_GET_PERMS: 554 case XS_RELEASE: 555 case XS_GET_DOMAIN_PATH: 556 case XS_WRITE: 557 case XS_MKDIR: 558 case XS_RM: 559 case XS_SET_PERMS: 560 /* send the request to xenstore and get feedback */ 561 rc = xenbus_dev_request_and_reply(&xbs->u.msg, &reply); 562 if (rc) { 563 XENBUSDRV_DBPRINT((CE_WARN, 564 "xenbus_dev_request_and_reply failed")); 565 goto out; 566 } 567 568 /* handle transaction start/end */ 569 if (xbs->u.msg.type == XS_TRANSACTION_START) { 570 trans = kmem_alloc(sizeof (*trans), KM_SLEEP); 571 (void) ddi_strtoul((char *)reply, NULL, 0, 572 (unsigned long *)&trans->handle); 573 list_insert_tail(&xbs->transactions, (void *)trans); 574 } else if (xbs->u.msg.type == XS_TRANSACTION_END) { 575 /* try to find out the ending transaction */ 576 for (trans = (struct xenbus_dev_transaction *) 577 list_head(&xbs->transactions); trans; 578 trans = (struct xenbus_dev_transaction *) 579 list_next(&xbs->transactions, (void *)trans)) 580 if (trans->handle == 581 (xenbus_transaction_t) 582 xbs->u.msg.tx_id) 583 break; 584 ASSERT(trans); 585 /* free it, if we find it */ 586 list_remove(&xbs->transactions, (void *)trans); 587 kmem_free(trans, sizeof (*trans)); 588 } 589 590 /* prepare data for xenbusdrv_read() to get */ 591 rc = xenbusdrv_queue_reply(xbs, &xbs->u.msg, reply); 592 593 kmem_free(reply, xbs->u.msg.len + 1); 594 break; 595 default: 596 rc = EINVAL; 597 } 598 599 out: 600 xbs->len = 0; 601 return (rc); 602 } 603 604 /*ARGSUSED*/ 605 static int 606 xenbusdrv_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len, 607 size_t *maplen, uint_t model) 608 { 609 xenbus_dev_t *xbs; 610 int err; 611 612 xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev))); 613 614 if (off != 0 || len != PAGESIZE) 615 return (-1); 616 617 if (!DOMAIN_IS_INITDOMAIN(xen_info)) 618 return (-1); 619 620 err = devmap_umem_setup(dhp, xbs->dip, NULL, xb_xenstore_cookie(), 621 0, PAGESIZE, PROT_READ | PROT_WRITE | PROT_USER, 0, NULL); 622 623 if (err) 624 return (err); 625 626 *maplen = PAGESIZE; 627 628 return (0); 629 } 630 631 /*ARGSUSED*/ 632 static int 633 xenbusdrv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 634 int *rvalp) 635 { 636 xenbus_dev_t *xbs; 637 638 xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev))); 639 switch (cmd) { 640 case IOCTL_XENBUS_XENSTORE_EVTCHN: 641 *rvalp = xen_info->store_evtchn; 642 break; 643 case IOCTL_XENBUS_NOTIFY_UP: 644 xs_notify_xenstore_up(); 645 xbs->xenstore_inst = 1; 646 break; 647 default: 648 return (EINVAL); 649 } 650 651 return (0); 652 } 653