1*843e1988Sjohnlev /* 2*843e1988Sjohnlev * CDDL HEADER START 3*843e1988Sjohnlev * 4*843e1988Sjohnlev * The contents of this file are subject to the terms of the 5*843e1988Sjohnlev * Common Development and Distribution License (the "License"). 6*843e1988Sjohnlev * You may not use this file except in compliance with the License. 7*843e1988Sjohnlev * 8*843e1988Sjohnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*843e1988Sjohnlev * or http://www.opensolaris.org/os/licensing. 10*843e1988Sjohnlev * See the License for the specific language governing permissions 11*843e1988Sjohnlev * and limitations under the License. 12*843e1988Sjohnlev * 13*843e1988Sjohnlev * When distributing Covered Code, include this CDDL HEADER in each 14*843e1988Sjohnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*843e1988Sjohnlev * If applicable, add the following below this CDDL HEADER, with the 16*843e1988Sjohnlev * fields enclosed by brackets "[]" replaced with your own identifying 17*843e1988Sjohnlev * information: Portions Copyright [yyyy] [name of copyright owner] 18*843e1988Sjohnlev * 19*843e1988Sjohnlev * CDDL HEADER END 20*843e1988Sjohnlev */ 21*843e1988Sjohnlev 22*843e1988Sjohnlev /* 23*843e1988Sjohnlev * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*843e1988Sjohnlev * Use is subject to license terms. 25*843e1988Sjohnlev */ 26*843e1988Sjohnlev 27*843e1988Sjohnlev #pragma ident "%Z%%M% %I% %E% SMI" 28*843e1988Sjohnlev 29*843e1988Sjohnlev /* 30*843e1988Sjohnlev * A simple wrapper around the balloon kernel thread to allow userland 31*843e1988Sjohnlev * programs access to the balloon status. 32*843e1988Sjohnlev */ 33*843e1988Sjohnlev 34*843e1988Sjohnlev #include <sys/types.h> 35*843e1988Sjohnlev #include <sys/file.h> 36*843e1988Sjohnlev #include <sys/errno.h> 37*843e1988Sjohnlev #include <sys/open.h> 38*843e1988Sjohnlev #include <sys/cred.h> 39*843e1988Sjohnlev #include <sys/conf.h> 40*843e1988Sjohnlev #include <sys/stat.h> 41*843e1988Sjohnlev #include <sys/modctl.h> 42*843e1988Sjohnlev #include <sys/ddi.h> 43*843e1988Sjohnlev #include <sys/sunddi.h> 44*843e1988Sjohnlev #include <sys/hypervisor.h> 45*843e1988Sjohnlev #include <sys/sysmacros.h> 46*843e1988Sjohnlev #include <sys/balloon_impl.h> 47*843e1988Sjohnlev 48*843e1988Sjohnlev static dev_info_t *balloon_devi; 49*843e1988Sjohnlev 50*843e1988Sjohnlev /*ARGSUSED*/ 51*843e1988Sjohnlev static int 52*843e1988Sjohnlev balloon_getinfo(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, void **result) 53*843e1988Sjohnlev { 54*843e1988Sjohnlev if (getminor((dev_t)arg) != BALLOON_MINOR) 55*843e1988Sjohnlev return (DDI_FAILURE); 56*843e1988Sjohnlev 57*843e1988Sjohnlev switch (cmd) { 58*843e1988Sjohnlev case DDI_INFO_DEVT2DEVINFO: 59*843e1988Sjohnlev *result = balloon_devi; 60*843e1988Sjohnlev break; 61*843e1988Sjohnlev case DDI_INFO_DEVT2INSTANCE: 62*843e1988Sjohnlev *result = 0; 63*843e1988Sjohnlev break; 64*843e1988Sjohnlev default: 65*843e1988Sjohnlev return (DDI_FAILURE); 66*843e1988Sjohnlev } 67*843e1988Sjohnlev 68*843e1988Sjohnlev return (DDI_SUCCESS); 69*843e1988Sjohnlev } 70*843e1988Sjohnlev 71*843e1988Sjohnlev static int 72*843e1988Sjohnlev balloon_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 73*843e1988Sjohnlev { 74*843e1988Sjohnlev if (cmd != DDI_ATTACH) 75*843e1988Sjohnlev return (DDI_FAILURE); 76*843e1988Sjohnlev 77*843e1988Sjohnlev if (ddi_create_minor_node(devi, ddi_get_name(devi), S_IFCHR, 78*843e1988Sjohnlev ddi_get_instance(devi), DDI_PSEUDO, 0) != DDI_SUCCESS) 79*843e1988Sjohnlev return (DDI_FAILURE); 80*843e1988Sjohnlev 81*843e1988Sjohnlev balloon_devi = devi; 82*843e1988Sjohnlev ddi_report_dev(devi); 83*843e1988Sjohnlev return (DDI_SUCCESS); 84*843e1988Sjohnlev } 85*843e1988Sjohnlev 86*843e1988Sjohnlev static int 87*843e1988Sjohnlev balloon_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 88*843e1988Sjohnlev { 89*843e1988Sjohnlev if (cmd != DDI_DETACH) 90*843e1988Sjohnlev return (DDI_FAILURE); 91*843e1988Sjohnlev ddi_remove_minor_node(devi, NULL); 92*843e1988Sjohnlev balloon_devi = NULL; 93*843e1988Sjohnlev return (DDI_SUCCESS); 94*843e1988Sjohnlev } 95*843e1988Sjohnlev 96*843e1988Sjohnlev /*ARGSUSED1*/ 97*843e1988Sjohnlev static int 98*843e1988Sjohnlev balloon_open(dev_t *dev, int flag, int otyp, cred_t *cr) 99*843e1988Sjohnlev { 100*843e1988Sjohnlev return (getminor(*dev) == BALLOON_MINOR ? 0 : ENXIO); 101*843e1988Sjohnlev } 102*843e1988Sjohnlev 103*843e1988Sjohnlev /* 104*843e1988Sjohnlev * When asked for one of the balloon values, we simply query the balloon thread. 105*843e1988Sjohnlev */ 106*843e1988Sjohnlev /*ARGSUSED*/ 107*843e1988Sjohnlev static int 108*843e1988Sjohnlev balloon_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, 109*843e1988Sjohnlev int *rval_p) 110*843e1988Sjohnlev { 111*843e1988Sjohnlev int rval = 0; 112*843e1988Sjohnlev size_t value; 113*843e1988Sjohnlev 114*843e1988Sjohnlev switch (cmd) { 115*843e1988Sjohnlev case BLN_IOCTL_CURRENT: 116*843e1988Sjohnlev case BLN_IOCTL_TARGET: 117*843e1988Sjohnlev case BLN_IOCTL_LOW: 118*843e1988Sjohnlev case BLN_IOCTL_HIGH: 119*843e1988Sjohnlev case BLN_IOCTL_LIMIT: 120*843e1988Sjohnlev value = balloon_values(cmd); 121*843e1988Sjohnlev if (ddi_copyout((void *)&value, (void *)arg, sizeof (value), 122*843e1988Sjohnlev mode)) 123*843e1988Sjohnlev return (EFAULT); 124*843e1988Sjohnlev break; 125*843e1988Sjohnlev default: 126*843e1988Sjohnlev rval = EINVAL; 127*843e1988Sjohnlev break; 128*843e1988Sjohnlev } 129*843e1988Sjohnlev return (rval); 130*843e1988Sjohnlev } 131*843e1988Sjohnlev 132*843e1988Sjohnlev static struct cb_ops balloon_cb_ops = { 133*843e1988Sjohnlev balloon_open, 134*843e1988Sjohnlev nulldev, /* close */ 135*843e1988Sjohnlev nodev, /* strategy */ 136*843e1988Sjohnlev nodev, /* print */ 137*843e1988Sjohnlev nodev, /* dump */ 138*843e1988Sjohnlev nodev, /* read */ 139*843e1988Sjohnlev nodev, /* write */ 140*843e1988Sjohnlev balloon_ioctl, /* ioctl */ 141*843e1988Sjohnlev nodev, /* devmap */ 142*843e1988Sjohnlev nodev, /* mmap */ 143*843e1988Sjohnlev nodev, /* segmap */ 144*843e1988Sjohnlev nochpoll, /* poll */ 145*843e1988Sjohnlev ddi_prop_op, 146*843e1988Sjohnlev NULL, 147*843e1988Sjohnlev D_64BIT | D_MP, 148*843e1988Sjohnlev CB_REV, 149*843e1988Sjohnlev NULL, 150*843e1988Sjohnlev NULL 151*843e1988Sjohnlev }; 152*843e1988Sjohnlev 153*843e1988Sjohnlev static struct dev_ops balloon_dv_ops = { 154*843e1988Sjohnlev DEVO_REV, 155*843e1988Sjohnlev 0, 156*843e1988Sjohnlev balloon_getinfo, 157*843e1988Sjohnlev nulldev, /* identify */ 158*843e1988Sjohnlev nulldev, /* probe */ 159*843e1988Sjohnlev balloon_attach, 160*843e1988Sjohnlev balloon_detach, 161*843e1988Sjohnlev nodev, /* reset */ 162*843e1988Sjohnlev &balloon_cb_ops, 163*843e1988Sjohnlev NULL, /* struct bus_ops */ 164*843e1988Sjohnlev NULL /* power */ 165*843e1988Sjohnlev }; 166*843e1988Sjohnlev 167*843e1988Sjohnlev static struct modldrv modldrv = { 168*843e1988Sjohnlev &mod_driverops, 169*843e1988Sjohnlev "balloon driver 1.1", 170*843e1988Sjohnlev &balloon_dv_ops 171*843e1988Sjohnlev }; 172*843e1988Sjohnlev 173*843e1988Sjohnlev static struct modlinkage modl = { 174*843e1988Sjohnlev MODREV_1, 175*843e1988Sjohnlev { 176*843e1988Sjohnlev (void *)&modldrv, 177*843e1988Sjohnlev NULL /* null termination */ 178*843e1988Sjohnlev } 179*843e1988Sjohnlev }; 180*843e1988Sjohnlev 181*843e1988Sjohnlev int 182*843e1988Sjohnlev _init(void) 183*843e1988Sjohnlev { 184*843e1988Sjohnlev return (mod_install(&modl)); 185*843e1988Sjohnlev } 186*843e1988Sjohnlev 187*843e1988Sjohnlev int 188*843e1988Sjohnlev _fini(void) 189*843e1988Sjohnlev { 190*843e1988Sjohnlev return (mod_remove(&modl)); 191*843e1988Sjohnlev } 192*843e1988Sjohnlev 193*843e1988Sjohnlev int 194*843e1988Sjohnlev _info(struct modinfo *modinfo) 195*843e1988Sjohnlev { 196*843e1988Sjohnlev return (mod_info(&modl, modinfo)); 197*843e1988Sjohnlev } 198