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