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