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, NULL }
 193 };
 194 
 195 int
 196 _init(void)
 197 {
 198         int e;
 199 
 200         e = ddi_soft_state_init(&xenbusdrv_statep, sizeof (xenbus_dev_t), 1);
 201         if (e)
 202                 return (e);
 203 
 204         e = mod_install(&modlinkage);
 205         if (e)
 206                 ddi_soft_state_fini(&xenbusdrv_statep);
 207 
 208         return (e);
 209 }
 210 
 211 int
 212 _fini(void)
 213 {
 214         int e;
 215 
 216         e = mod_remove(&modlinkage);
 217         if (e)
 218                 return (e);
 219 
 220         ddi_soft_state_fini(&xenbusdrv_statep);
 221 
 222         return (0);
 223 }
 224 
 225 int
 226 _info(struct modinfo *modinfop)
 227 {
 228         return (mod_info(&modlinkage, modinfop));
 229 }
 230 
 231 /* ARGSUSED */
 232 static int
 233 xenbusdrv_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
 234 {
 235         dev_t   dev = (dev_t)arg;
 236         minor_t minor = getminor(dev);
 237         int     retval;
 238 
 239         switch (cmd) {
 240         case DDI_INFO_DEVT2DEVINFO:
 241                 if (minor != 0 || xenbusdrv_dip == NULL) {
 242                         *result = (void *)NULL;
 243                         retval = DDI_FAILURE;
 244                 } else {
 245                         *result = (void *)xenbusdrv_dip;
 246                         retval = DDI_SUCCESS;
 247                 }
 248                 break;
 249         case DDI_INFO_DEVT2INSTANCE:
 250                 *result = (void *)0;
 251                 retval = DDI_SUCCESS;
 252                 break;
 253         default:
 254                 retval = DDI_FAILURE;
 255         }
 256         return (retval);
 257 }
 258 
 259 static int
 260 xenbusdrv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 261 {
 262         int     error;
 263         int     unit = ddi_get_instance(dip);
 264 
 265 
 266         switch (cmd) {
 267         case DDI_ATTACH:
 268                 break;
 269         case DDI_RESUME:
 270                 return (DDI_SUCCESS);
 271         default:
 272                 cmn_err(CE_WARN, "xenbus_attach: unknown cmd 0x%x\n", cmd);
 273                 return (DDI_FAILURE);
 274         }
 275 
 276         /* DDI_ATTACH */
 277 
 278         /*
 279          * only one instance - but we clone using the open routine
 280          */
 281         if (ddi_get_instance(dip) > 0)
 282                 return (DDI_FAILURE);
 283 
 284         mutex_init(&xenbusdrv_clone_tab_mutex, NULL, MUTEX_DRIVER,
 285             NULL);
 286 
 287         error = ddi_create_minor_node(dip, "xenbus", S_IFCHR, unit,
 288             DDI_PSEUDO, NULL);
 289         if (error != DDI_SUCCESS)
 290                 goto fail;
 291 
 292         /*
 293          * save dip for getinfo
 294          */
 295         xenbusdrv_dip = dip;
 296         ddi_report_dev(dip);
 297 
 298 #ifndef XPV_HVM_DRIVER
 299         if (DOMAIN_IS_INITDOMAIN(xen_info))
 300                 xs_dom0_init();
 301 #endif
 302 
 303         return (DDI_SUCCESS);
 304 
 305 fail:
 306         (void) xenbusdrv_detach(dip, DDI_DETACH);
 307         return (error);
 308 }
 309 
 310 static int
 311 xenbusdrv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 312 {
 313         /*
 314          * again, only one instance
 315          */
 316         if (ddi_get_instance(dip) > 0)
 317                 return (DDI_FAILURE);
 318 
 319         switch (cmd) {
 320         case DDI_DETACH:
 321                 ddi_remove_minor_node(dip, NULL);
 322                 mutex_destroy(&xenbusdrv_clone_tab_mutex);
 323                 xenbusdrv_dip = NULL;
 324                 return (DDI_SUCCESS);
 325         case DDI_SUSPEND:
 326                 return (DDI_SUCCESS);
 327         default:
 328                 cmn_err(CE_WARN, "xenbus_detach: unknown cmd 0x%x\n", cmd);
 329                 return (DDI_FAILURE);
 330         }
 331 }
 332 
 333 /* ARGSUSED */
 334 static int
 335 xenbusdrv_open(dev_t *devp, int flag, int otyp, cred_t *cr)
 336 {
 337         xenbus_dev_t *xbs;
 338         minor_t minor = getminor(*devp);
 339 
 340         if (otyp == OTYP_BLK)
 341                 return (ENXIO);
 342 
 343         /*
 344          * only allow open on minor = 0 - the clone device
 345          */
 346         if (minor != 0)
 347                 return (ENXIO);
 348 
 349         /*
 350          * find a free slot and grab it
 351          */
 352         mutex_enter(&xenbusdrv_clone_tab_mutex);
 353         for (minor = 1; minor < XENBUSDRV_NCLONES; minor++) {
 354                 if (xenbusdrv_clone_tab[minor] == 0) {
 355                         xenbusdrv_clone_tab[minor] = 1;
 356                         break;
 357                 }
 358         }
 359         mutex_exit(&xenbusdrv_clone_tab_mutex);
 360         if (minor == XENBUSDRV_NCLONES)
 361                 return (EAGAIN);
 362 
 363         /* Allocate softstate structure */
 364         if (ddi_soft_state_zalloc(xenbusdrv_statep,
 365             XENBUSDRV_MINOR2INST(minor)) != DDI_SUCCESS) {
 366                 mutex_enter(&xenbusdrv_clone_tab_mutex);
 367                 xenbusdrv_clone_tab[minor] = 0;
 368                 mutex_exit(&xenbusdrv_clone_tab_mutex);
 369                 return (EAGAIN);
 370         }
 371         xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(minor));
 372 
 373         /* ... and init it */
 374         xbs->dip = xenbusdrv_dip;
 375         mutex_init(&xbs->read_mutex, NULL, MUTEX_DRIVER, NULL);
 376         cv_init(&xbs->read_cv, NULL, CV_DEFAULT, NULL);
 377         list_create(&xbs->transactions, sizeof (struct xenbus_dev_transaction),
 378             offsetof(struct xenbus_dev_transaction, list));
 379 
 380         /* clone driver */
 381         *devp = makedevice(getmajor(*devp), minor);
 382         XENBUSDRV_DBPRINT((CE_NOTE, "Xenbus drv open succeeded, minor=%d",
 383             minor));
 384 
 385         return (0);
 386 }
 387 
 388 /* ARGSUSED */
 389 static int
 390 xenbusdrv_close(dev_t dev, int flag, int otyp, struct cred *cr)
 391 {
 392         xenbus_dev_t *xbs;
 393         minor_t minor = getminor(dev);
 394         struct xenbus_dev_transaction *trans;
 395 
 396         xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(minor));
 397         if (xbs == NULL)
 398                 return (ENXIO);
 399 
 400 #ifdef notyet
 401         /*
 402          * XXPV - would like to be able to notify xenstore down here, but
 403          * as the daemon is currently written, it doesn't leave the device
 404          * open after initial setup, so we have no way of knowing if it has
 405          * gone away.
 406          */
 407         if (xbs->xenstore_inst)
 408                 xs_notify_xenstore_down();
 409 #endif
 410         /* free pending transaction */
 411         while (trans = (struct xenbus_dev_transaction *)
 412             list_head(&xbs->transactions)) {
 413                 (void) xenbus_transaction_end(trans->handle, 1);
 414                 list_remove(&xbs->transactions, (void *)trans);
 415                 kmem_free(trans, sizeof (*trans));
 416         }
 417 
 418         mutex_destroy(&xbs->read_mutex);
 419         cv_destroy(&xbs->read_cv);
 420         ddi_soft_state_free(xenbusdrv_statep, XENBUSDRV_MINOR2INST(minor));
 421 
 422         /*
 423          * free clone tab slot
 424          */
 425         mutex_enter(&xenbusdrv_clone_tab_mutex);
 426         xenbusdrv_clone_tab[minor] = 0;
 427         mutex_exit(&xenbusdrv_clone_tab_mutex);
 428 
 429         XENBUSDRV_DBPRINT((CE_NOTE, "Xenbus drv close succeeded, minor=%d",
 430             minor));
 431 
 432         return (0);
 433 }
 434 
 435 /* ARGSUSED */
 436 static int
 437 xenbusdrv_read(dev_t dev, struct uio *uiop, cred_t *cr)
 438 {
 439         xenbus_dev_t *xbs;
 440         size_t len;
 441         int res, ret;
 442         int idx;
 443 
 444         XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_read called"));
 445 
 446         if (secpolicy_xvm_control(cr))
 447                 return (EPERM);
 448 
 449         xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev)));
 450 
 451         mutex_enter(&xbs->read_mutex);
 452 
 453         /* check if we have something to read */
 454         while (xbs->read_prod == xbs->read_cons) {
 455                 if (cv_wait_sig(&xbs->read_cv, &xbs->read_mutex) == 0) {
 456                         mutex_exit(&xbs->read_mutex);
 457                         return (EINTR);
 458                 }
 459         }
 460 
 461         idx = XENBUSDRV_MASK_READ_IDX(xbs->read_cons);
 462         res = uiop->uio_resid;
 463 
 464         len = xbs->read_prod - xbs->read_cons;
 465 
 466         if (len > (sizeof (xbs->read_buffer) - idx))
 467                 len = sizeof (xbs->read_buffer) - idx;
 468         if (len > res)
 469                 len = res;
 470 
 471         ret = uiomove(xbs->read_buffer + idx, len, UIO_READ, uiop);
 472         xbs->read_cons += res - uiop->uio_resid;
 473         mutex_exit(&xbs->read_mutex);
 474 
 475         return (ret);
 476 }
 477 
 478 /*
 479  * prepare data for xenbusdrv_read()
 480  */
 481 static int
 482 xenbusdrv_queue_reply(xenbus_dev_t *xbs, const struct xsd_sockmsg *msg,
 483     const char *reply)
 484 {
 485         int i;
 486         int remaining;
 487 
 488         XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_queue_reply called"));
 489 
 490         mutex_enter(&xbs->read_mutex);
 491 
 492         remaining = sizeof (xbs->read_buffer) -
 493             (xbs->read_prod - xbs->read_cons);
 494 
 495         if (sizeof (*msg) + msg->len > remaining) {
 496                 mutex_exit(&xbs->read_mutex);
 497                 return (EOVERFLOW);
 498         }
 499 
 500         for (i = 0; i < sizeof (*msg); i++, xbs->read_prod++) {
 501                 xbs->read_buffer[XENBUSDRV_MASK_READ_IDX(xbs->read_prod)] =
 502                     ((char *)msg)[i];
 503         }
 504 
 505         for (i = 0; i < msg->len; i++, xbs->read_prod++) {
 506                 xbs->read_buffer[XENBUSDRV_MASK_READ_IDX(xbs->read_prod)] =
 507                     reply[i];
 508         }
 509 
 510         cv_broadcast(&xbs->read_cv);
 511 
 512         mutex_exit(&xbs->read_mutex);
 513 
 514         XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_queue_reply exited"));
 515 
 516         return (0);
 517 }
 518 
 519 /* ARGSUSED */
 520 static int
 521 xenbusdrv_write(dev_t dev, struct uio *uiop, cred_t *cr)
 522 {
 523         xenbus_dev_t *xbs;
 524         struct xenbus_dev_transaction *trans;
 525         void *reply;
 526         size_t len;
 527         int rc = 0;
 528 
 529         XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_write called"));
 530 
 531         if (secpolicy_xvm_control(cr))
 532                 return (EPERM);
 533 
 534         xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev)));
 535         len = uiop->uio_resid;
 536 
 537         if ((len + xbs->len) > sizeof (xbs->u.buffer)) {
 538                 XENBUSDRV_DBPRINT((CE_WARN, "Request is too big"));
 539                 rc = EINVAL;
 540                 goto out;
 541         }
 542 
 543         if (uiomove(xbs->u.buffer + xbs->len, len, UIO_WRITE, uiop) != 0) {
 544                 XENBUSDRV_DBPRINT((CE_WARN, "Uiomove failed"));
 545                 rc = EFAULT;
 546                 goto out;
 547         }
 548 
 549         xbs->len += len;
 550 
 551         if (xbs->len < (sizeof (xbs->u.msg)) ||
 552             xbs->len < (sizeof (xbs->u.msg) + xbs->u.msg.len)) {
 553                 XENBUSDRV_DBPRINT((CE_NOTE, "Partial request"));
 554                 return (0);
 555         }
 556 
 557         switch (xbs->u.msg.type) {
 558         case XS_TRANSACTION_START:
 559         case XS_TRANSACTION_END:
 560         case XS_DIRECTORY:
 561         case XS_READ:
 562         case XS_GET_PERMS:
 563         case XS_RELEASE:
 564         case XS_GET_DOMAIN_PATH:
 565         case XS_WRITE:
 566         case XS_MKDIR:
 567         case XS_RM:
 568         case XS_SET_PERMS:
 569                 /* send the request to xenstore and get feedback */
 570                 rc = xenbus_dev_request_and_reply(&xbs->u.msg, &reply);
 571                 if (rc) {
 572                         XENBUSDRV_DBPRINT((CE_WARN,
 573                             "xenbus_dev_request_and_reply failed"));
 574                         goto out;
 575                 }
 576 
 577                 /* handle transaction start/end */
 578                 if (xbs->u.msg.type == XS_TRANSACTION_START) {
 579                         trans = kmem_alloc(sizeof (*trans), KM_SLEEP);
 580                         (void) ddi_strtoul((char *)reply, NULL, 0,
 581                             (unsigned long *)&trans->handle);
 582                         list_insert_tail(&xbs->transactions, (void *)trans);
 583                 } else if (xbs->u.msg.type == XS_TRANSACTION_END) {
 584                         /* try to find out the ending transaction */
 585                         for (trans = (struct xenbus_dev_transaction *)
 586                             list_head(&xbs->transactions); trans;
 587                             trans = (struct xenbus_dev_transaction *)
 588                             list_next(&xbs->transactions, (void *)trans))
 589                                 if (trans->handle ==
 590                                     (xenbus_transaction_t)
 591                                     xbs->u.msg.tx_id)
 592                                         break;
 593                         ASSERT(trans);
 594                         /* free it, if we find it */
 595                         list_remove(&xbs->transactions, (void *)trans);
 596                         kmem_free(trans, sizeof (*trans));
 597                 }
 598 
 599                 /* prepare data for xenbusdrv_read() to get */
 600                 rc = xenbusdrv_queue_reply(xbs, &xbs->u.msg, reply);
 601 
 602                 kmem_free(reply, xbs->u.msg.len + 1);
 603                 break;
 604         default:
 605                 rc = EINVAL;
 606         }
 607 
 608 out:
 609         xbs->len = 0;
 610         return (rc);
 611 }
 612 
 613 /*ARGSUSED*/
 614 static int
 615 xenbusdrv_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
 616     size_t *maplen, uint_t model)
 617 {
 618         xenbus_dev_t *xbs;
 619         int err;
 620 
 621         xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev)));
 622 
 623         if (off != 0 || len != PAGESIZE)
 624                 return (-1);
 625 
 626         if (!DOMAIN_IS_INITDOMAIN(xen_info))
 627                 return (-1);
 628 
 629         err = devmap_umem_setup(dhp, xbs->dip, NULL, xb_xenstore_cookie(),
 630             0, PAGESIZE, PROT_READ | PROT_WRITE | PROT_USER, 0, NULL);
 631 
 632         if (err)
 633                 return (err);
 634 
 635         *maplen = PAGESIZE;
 636 
 637         return (0);
 638 }
 639 
 640 static int
 641 xenbusdrv_segmap(dev_t dev, off_t off, ddi_as_handle_t as, caddr_t *addrp,
 642     off_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr)
 643 {
 644 
 645         if (secpolicy_xvm_control(cr))
 646                 return (EPERM);
 647 
 648         return (ddi_devmap_segmap(dev, off, as, addrp, len, prot,
 649             maxprot, flags, cr));
 650 }
 651 
 652 /*ARGSUSED*/
 653 static int
 654 xenbusdrv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr,
 655     int *rvalp)
 656 {
 657         xenbus_dev_t *xbs;
 658 
 659         if (secpolicy_xvm_control(cr))
 660                 return (EPERM);
 661 
 662         xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev)));
 663         switch (cmd) {
 664         case IOCTL_XENBUS_XENSTORE_EVTCHN:
 665                 *rvalp = xen_info->store_evtchn;
 666                 break;
 667         case IOCTL_XENBUS_NOTIFY_UP:
 668                 xs_notify_xenstore_up();
 669                 xbs->xenstore_inst = 1;
 670                 break;
 671         default:
 672                 return (EINVAL);
 673         }
 674 
 675         return (0);
 676 }