1843e1988Sjohnlev /* 2843e1988Sjohnlev * CDDL HEADER START 3843e1988Sjohnlev * 4843e1988Sjohnlev * The contents of this file are subject to the terms of the 5843e1988Sjohnlev * Common Development and Distribution License (the "License"). 6843e1988Sjohnlev * You may not use this file except in compliance with the License. 7843e1988Sjohnlev * 8843e1988Sjohnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9843e1988Sjohnlev * or http://www.opensolaris.org/os/licensing. 10843e1988Sjohnlev * See the License for the specific language governing permissions 11843e1988Sjohnlev * and limitations under the License. 12843e1988Sjohnlev * 13843e1988Sjohnlev * When distributing Covered Code, include this CDDL HEADER in each 14843e1988Sjohnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15843e1988Sjohnlev * If applicable, add the following below this CDDL HEADER, with the 16843e1988Sjohnlev * fields enclosed by brackets "[]" replaced with your own identifying 17843e1988Sjohnlev * information: Portions Copyright [yyyy] [name of copyright owner] 18843e1988Sjohnlev * 19843e1988Sjohnlev * CDDL HEADER END 20843e1988Sjohnlev */ 21843e1988Sjohnlev 22843e1988Sjohnlev /* 23*19397407SSherry Moore * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24843e1988Sjohnlev * Use is subject to license terms. 25843e1988Sjohnlev */ 26843e1988Sjohnlev 27843e1988Sjohnlev 28843e1988Sjohnlev /* 29843e1988Sjohnlev * A simple wrapper around the balloon kernel thread to allow userland 30843e1988Sjohnlev * programs access to the balloon status. 31843e1988Sjohnlev */ 32843e1988Sjohnlev 33843e1988Sjohnlev #include <sys/types.h> 34843e1988Sjohnlev #include <sys/file.h> 35843e1988Sjohnlev #include <sys/errno.h> 36843e1988Sjohnlev #include <sys/open.h> 37843e1988Sjohnlev #include <sys/cred.h> 38843e1988Sjohnlev #include <sys/conf.h> 39843e1988Sjohnlev #include <sys/stat.h> 40843e1988Sjohnlev #include <sys/modctl.h> 41843e1988Sjohnlev #include <sys/ddi.h> 42843e1988Sjohnlev #include <sys/sunddi.h> 43843e1988Sjohnlev #include <sys/hypervisor.h> 44843e1988Sjohnlev #include <sys/sysmacros.h> 45843e1988Sjohnlev #include <sys/balloon_impl.h> 46843e1988Sjohnlev 47843e1988Sjohnlev static dev_info_t *balloon_devi; 48843e1988Sjohnlev 49843e1988Sjohnlev /*ARGSUSED*/ 50843e1988Sjohnlev static int 51843e1988Sjohnlev balloon_getinfo(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, void **result) 52843e1988Sjohnlev { 53843e1988Sjohnlev if (getminor((dev_t)arg) != BALLOON_MINOR) 54843e1988Sjohnlev return (DDI_FAILURE); 55843e1988Sjohnlev 56843e1988Sjohnlev switch (cmd) { 57843e1988Sjohnlev case DDI_INFO_DEVT2DEVINFO: 58843e1988Sjohnlev *result = balloon_devi; 59843e1988Sjohnlev break; 60843e1988Sjohnlev case DDI_INFO_DEVT2INSTANCE: 61843e1988Sjohnlev *result = 0; 62843e1988Sjohnlev break; 63843e1988Sjohnlev default: 64843e1988Sjohnlev return (DDI_FAILURE); 65843e1988Sjohnlev } 66843e1988Sjohnlev 67843e1988Sjohnlev return (DDI_SUCCESS); 68843e1988Sjohnlev } 69843e1988Sjohnlev 70843e1988Sjohnlev static int 71843e1988Sjohnlev balloon_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 72843e1988Sjohnlev { 73843e1988Sjohnlev if (cmd != DDI_ATTACH) 74843e1988Sjohnlev return (DDI_FAILURE); 75843e1988Sjohnlev 76843e1988Sjohnlev if (ddi_create_minor_node(devi, ddi_get_name(devi), S_IFCHR, 77843e1988Sjohnlev ddi_get_instance(devi), DDI_PSEUDO, 0) != DDI_SUCCESS) 78843e1988Sjohnlev return (DDI_FAILURE); 79843e1988Sjohnlev 80843e1988Sjohnlev balloon_devi = devi; 81843e1988Sjohnlev ddi_report_dev(devi); 82843e1988Sjohnlev return (DDI_SUCCESS); 83843e1988Sjohnlev } 84843e1988Sjohnlev 85843e1988Sjohnlev static int 86843e1988Sjohnlev balloon_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 87843e1988Sjohnlev { 88843e1988Sjohnlev if (cmd != DDI_DETACH) 89843e1988Sjohnlev return (DDI_FAILURE); 90843e1988Sjohnlev ddi_remove_minor_node(devi, NULL); 91843e1988Sjohnlev balloon_devi = NULL; 92843e1988Sjohnlev return (DDI_SUCCESS); 93843e1988Sjohnlev } 94843e1988Sjohnlev 95843e1988Sjohnlev /*ARGSUSED1*/ 96843e1988Sjohnlev static int 97843e1988Sjohnlev balloon_open(dev_t *dev, int flag, int otyp, cred_t *cr) 98843e1988Sjohnlev { 99843e1988Sjohnlev return (getminor(*dev) == BALLOON_MINOR ? 0 : ENXIO); 100843e1988Sjohnlev } 101843e1988Sjohnlev 102843e1988Sjohnlev /* 103843e1988Sjohnlev * When asked for one of the balloon values, we simply query the balloon thread. 104843e1988Sjohnlev */ 105843e1988Sjohnlev /*ARGSUSED*/ 106843e1988Sjohnlev static int 107843e1988Sjohnlev balloon_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, 108843e1988Sjohnlev int *rval_p) 109843e1988Sjohnlev { 110843e1988Sjohnlev int rval = 0; 111843e1988Sjohnlev size_t value; 112843e1988Sjohnlev 113843e1988Sjohnlev switch (cmd) { 114843e1988Sjohnlev case BLN_IOCTL_CURRENT: 115843e1988Sjohnlev case BLN_IOCTL_TARGET: 116843e1988Sjohnlev case BLN_IOCTL_LOW: 117843e1988Sjohnlev case BLN_IOCTL_HIGH: 118843e1988Sjohnlev case BLN_IOCTL_LIMIT: 119843e1988Sjohnlev value = balloon_values(cmd); 120843e1988Sjohnlev if (ddi_copyout((void *)&value, (void *)arg, sizeof (value), 121843e1988Sjohnlev mode)) 122843e1988Sjohnlev return (EFAULT); 123843e1988Sjohnlev break; 124843e1988Sjohnlev default: 125843e1988Sjohnlev rval = EINVAL; 126843e1988Sjohnlev break; 127843e1988Sjohnlev } 128843e1988Sjohnlev return (rval); 129843e1988Sjohnlev } 130843e1988Sjohnlev 131843e1988Sjohnlev static struct cb_ops balloon_cb_ops = { 132843e1988Sjohnlev balloon_open, 133843e1988Sjohnlev nulldev, /* close */ 134843e1988Sjohnlev nodev, /* strategy */ 135843e1988Sjohnlev nodev, /* print */ 136843e1988Sjohnlev nodev, /* dump */ 137843e1988Sjohnlev nodev, /* read */ 138843e1988Sjohnlev nodev, /* write */ 139843e1988Sjohnlev balloon_ioctl, /* ioctl */ 140843e1988Sjohnlev nodev, /* devmap */ 141843e1988Sjohnlev nodev, /* mmap */ 142843e1988Sjohnlev nodev, /* segmap */ 143843e1988Sjohnlev nochpoll, /* poll */ 144843e1988Sjohnlev ddi_prop_op, 145843e1988Sjohnlev NULL, 146843e1988Sjohnlev D_64BIT | D_MP, 147843e1988Sjohnlev CB_REV, 148843e1988Sjohnlev NULL, 149843e1988Sjohnlev NULL 150843e1988Sjohnlev }; 151843e1988Sjohnlev 152843e1988Sjohnlev static struct dev_ops balloon_dv_ops = { 153843e1988Sjohnlev DEVO_REV, 154843e1988Sjohnlev 0, 155843e1988Sjohnlev balloon_getinfo, 156843e1988Sjohnlev nulldev, /* identify */ 157843e1988Sjohnlev nulldev, /* probe */ 158843e1988Sjohnlev balloon_attach, 159843e1988Sjohnlev balloon_detach, 160843e1988Sjohnlev nodev, /* reset */ 161843e1988Sjohnlev &balloon_cb_ops, 162843e1988Sjohnlev NULL, /* struct bus_ops */ 163*19397407SSherry Moore NULL, /* power */ 164*19397407SSherry Moore ddi_quiesce_not_needed, /* quiesce */ 165843e1988Sjohnlev }; 166843e1988Sjohnlev 167843e1988Sjohnlev static struct modldrv modldrv = { 168843e1988Sjohnlev &mod_driverops, 169*19397407SSherry Moore "balloon driver", 170843e1988Sjohnlev &balloon_dv_ops 171843e1988Sjohnlev }; 172843e1988Sjohnlev 173843e1988Sjohnlev static struct modlinkage modl = { 174843e1988Sjohnlev MODREV_1, 175843e1988Sjohnlev { 176843e1988Sjohnlev (void *)&modldrv, 177843e1988Sjohnlev NULL /* null termination */ 178843e1988Sjohnlev } 179843e1988Sjohnlev }; 180843e1988Sjohnlev 181843e1988Sjohnlev int 182843e1988Sjohnlev _init(void) 183843e1988Sjohnlev { 184843e1988Sjohnlev return (mod_install(&modl)); 185843e1988Sjohnlev } 186843e1988Sjohnlev 187843e1988Sjohnlev int 188843e1988Sjohnlev _fini(void) 189843e1988Sjohnlev { 190843e1988Sjohnlev return (mod_remove(&modl)); 191843e1988Sjohnlev } 192843e1988Sjohnlev 193843e1988Sjohnlev int 194843e1988Sjohnlev _info(struct modinfo *modinfo) 195843e1988Sjohnlev { 196843e1988Sjohnlev return (mod_info(&modl, modinfo)); 197843e1988Sjohnlev } 198