1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2002 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Dump driver. Provides ioctls to get/set crash dump configuration. 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/dumphdr.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/dumpadm.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/pathname.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 46*7c478bd9Sstevel@tonic-gate #include <vm/anon.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate static dev_info_t *dump_devi; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate static int 55*7c478bd9Sstevel@tonic-gate dump_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 56*7c478bd9Sstevel@tonic-gate { 57*7c478bd9Sstevel@tonic-gate if (cmd != DDI_ATTACH) 58*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 59*7c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(devi, "dump", S_IFCHR, 0, DDI_PSEUDO, NULL) == 60*7c478bd9Sstevel@tonic-gate DDI_FAILURE) { 61*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(devi, NULL); 62*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 63*7c478bd9Sstevel@tonic-gate } 64*7c478bd9Sstevel@tonic-gate dump_devi = devi; 65*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 66*7c478bd9Sstevel@tonic-gate } 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate static int 69*7c478bd9Sstevel@tonic-gate dump_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 70*7c478bd9Sstevel@tonic-gate { 71*7c478bd9Sstevel@tonic-gate if (cmd != DDI_DETACH) 72*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 73*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(devi, NULL); 74*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 75*7c478bd9Sstevel@tonic-gate } 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 78*7c478bd9Sstevel@tonic-gate static int 79*7c478bd9Sstevel@tonic-gate dump_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 80*7c478bd9Sstevel@tonic-gate { 81*7c478bd9Sstevel@tonic-gate switch (infocmd) { 82*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 83*7c478bd9Sstevel@tonic-gate *result = dump_devi; 84*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 85*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 86*7c478bd9Sstevel@tonic-gate *result = 0; 87*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 88*7c478bd9Sstevel@tonic-gate } 89*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 90*7c478bd9Sstevel@tonic-gate } 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 93*7c478bd9Sstevel@tonic-gate int 94*7c478bd9Sstevel@tonic-gate dump_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred, int *rvalp) 95*7c478bd9Sstevel@tonic-gate { 96*7c478bd9Sstevel@tonic-gate uint64_t size; 97*7c478bd9Sstevel@tonic-gate uint64_t dumpsize_in_pages; 98*7c478bd9Sstevel@tonic-gate int error = 0; 99*7c478bd9Sstevel@tonic-gate char *pathbuf = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 100*7c478bd9Sstevel@tonic-gate vnode_t *vp; 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate switch (cmd) { 103*7c478bd9Sstevel@tonic-gate case DIOCGETDUMPSIZE: 104*7c478bd9Sstevel@tonic-gate if (dump_conflags & DUMP_ALL) 105*7c478bd9Sstevel@tonic-gate size = ptob((uint64_t)physmem) / DUMP_COMPRESS_RATIO; 106*7c478bd9Sstevel@tonic-gate else { 107*7c478bd9Sstevel@tonic-gate /* 108*7c478bd9Sstevel@tonic-gate * We can't give a good answer for the DUMP_CURPROC 109*7c478bd9Sstevel@tonic-gate * because we won't know which process to use until it 110*7c478bd9Sstevel@tonic-gate * causes a panic. We'll therefore punt and give the 111*7c478bd9Sstevel@tonic-gate * caller the size for the kernel. 112*7c478bd9Sstevel@tonic-gate * 113*7c478bd9Sstevel@tonic-gate * This kernel size equation takes care of the 114*7c478bd9Sstevel@tonic-gate * boot time kernel footprint and also accounts 115*7c478bd9Sstevel@tonic-gate * for availrmem changes due to user explicit locking. 116*7c478bd9Sstevel@tonic-gate * Refer to common/vm/vm_page.c for an explanation 117*7c478bd9Sstevel@tonic-gate * of these counters. 118*7c478bd9Sstevel@tonic-gate */ 119*7c478bd9Sstevel@tonic-gate dumpsize_in_pages = (physinstalled - obp_pages - 120*7c478bd9Sstevel@tonic-gate availrmem - 121*7c478bd9Sstevel@tonic-gate anon_segkp_pages_locked - 122*7c478bd9Sstevel@tonic-gate k_anoninfo.ani_mem_resv - 123*7c478bd9Sstevel@tonic-gate segvn_pages_locked - 124*7c478bd9Sstevel@tonic-gate pages_locked - 125*7c478bd9Sstevel@tonic-gate pages_claimed - 126*7c478bd9Sstevel@tonic-gate pages_useclaim); 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate size = ptob(dumpsize_in_pages) / DUMP_COMPRESS_RATIO; 129*7c478bd9Sstevel@tonic-gate } 130*7c478bd9Sstevel@tonic-gate if (copyout(&size, (void *)arg, sizeof (size)) < 0) 131*7c478bd9Sstevel@tonic-gate error = EFAULT; 132*7c478bd9Sstevel@tonic-gate break; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate case DIOCGETCONF: 135*7c478bd9Sstevel@tonic-gate mutex_enter(&dump_lock); 136*7c478bd9Sstevel@tonic-gate *rvalp = dump_conflags; 137*7c478bd9Sstevel@tonic-gate if (dumpvp && !(dumpvp->v_flag & VISSWAP)) 138*7c478bd9Sstevel@tonic-gate *rvalp |= DUMP_EXCL; 139*7c478bd9Sstevel@tonic-gate mutex_exit(&dump_lock); 140*7c478bd9Sstevel@tonic-gate break; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate case DIOCSETCONF: 143*7c478bd9Sstevel@tonic-gate mutex_enter(&dump_lock); 144*7c478bd9Sstevel@tonic-gate if (arg == DUMP_KERNEL || arg == DUMP_ALL || 145*7c478bd9Sstevel@tonic-gate arg == DUMP_CURPROC) 146*7c478bd9Sstevel@tonic-gate dump_conflags = arg; 147*7c478bd9Sstevel@tonic-gate else 148*7c478bd9Sstevel@tonic-gate error = EINVAL; 149*7c478bd9Sstevel@tonic-gate mutex_exit(&dump_lock); 150*7c478bd9Sstevel@tonic-gate break; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate case DIOCGETDEV: 153*7c478bd9Sstevel@tonic-gate mutex_enter(&dump_lock); 154*7c478bd9Sstevel@tonic-gate if (dumppath == NULL) { 155*7c478bd9Sstevel@tonic-gate mutex_exit(&dump_lock); 156*7c478bd9Sstevel@tonic-gate error = ENODEV; 157*7c478bd9Sstevel@tonic-gate break; 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate (void) strcpy(pathbuf, dumppath); 160*7c478bd9Sstevel@tonic-gate mutex_exit(&dump_lock); 161*7c478bd9Sstevel@tonic-gate error = copyoutstr(pathbuf, (void *)arg, MAXPATHLEN, NULL); 162*7c478bd9Sstevel@tonic-gate break; 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate case DIOCSETDEV: 165*7c478bd9Sstevel@tonic-gate case DIOCTRYDEV: 166*7c478bd9Sstevel@tonic-gate if ((error = copyinstr((char *)arg, pathbuf, MAXPATHLEN, 167*7c478bd9Sstevel@tonic-gate NULL)) != 0 || (error = lookupname(pathbuf, UIO_SYSSPACE, 168*7c478bd9Sstevel@tonic-gate FOLLOW, NULLVPP, &vp)) != 0) 169*7c478bd9Sstevel@tonic-gate break; 170*7c478bd9Sstevel@tonic-gate mutex_enter(&dump_lock); 171*7c478bd9Sstevel@tonic-gate error = dumpinit(vp, pathbuf, cmd == DIOCTRYDEV); 172*7c478bd9Sstevel@tonic-gate mutex_exit(&dump_lock); 173*7c478bd9Sstevel@tonic-gate VN_RELE(vp); 174*7c478bd9Sstevel@tonic-gate break; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate case DIOCDUMP: 177*7c478bd9Sstevel@tonic-gate mutex_enter(&dump_lock); 178*7c478bd9Sstevel@tonic-gate if (dumpvp == NULL) 179*7c478bd9Sstevel@tonic-gate error = ENODEV; 180*7c478bd9Sstevel@tonic-gate else if (dumpvp->v_flag & VISSWAP) 181*7c478bd9Sstevel@tonic-gate error = EBUSY; 182*7c478bd9Sstevel@tonic-gate else 183*7c478bd9Sstevel@tonic-gate dumpsys(); 184*7c478bd9Sstevel@tonic-gate mutex_exit(&dump_lock); 185*7c478bd9Sstevel@tonic-gate break; 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate default: 188*7c478bd9Sstevel@tonic-gate error = ENXIO; 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate kmem_free(pathbuf, MAXPATHLEN); 192*7c478bd9Sstevel@tonic-gate return (error); 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate struct cb_ops dump_cb_ops = { 196*7c478bd9Sstevel@tonic-gate nulldev, /* open */ 197*7c478bd9Sstevel@tonic-gate nulldev, /* close */ 198*7c478bd9Sstevel@tonic-gate nodev, /* strategy */ 199*7c478bd9Sstevel@tonic-gate nodev, /* print */ 200*7c478bd9Sstevel@tonic-gate nodev, /* dump */ 201*7c478bd9Sstevel@tonic-gate nodev, /* read */ 202*7c478bd9Sstevel@tonic-gate nodev, /* write */ 203*7c478bd9Sstevel@tonic-gate dump_ioctl, /* ioctl */ 204*7c478bd9Sstevel@tonic-gate nodev, /* devmap */ 205*7c478bd9Sstevel@tonic-gate nodev, /* mmap */ 206*7c478bd9Sstevel@tonic-gate nodev, /* segmap */ 207*7c478bd9Sstevel@tonic-gate nochpoll, /* poll */ 208*7c478bd9Sstevel@tonic-gate ddi_prop_op, /* prop_op */ 209*7c478bd9Sstevel@tonic-gate 0, /* streamtab */ 210*7c478bd9Sstevel@tonic-gate D_NEW|D_MP /* Driver compatibility flag */ 211*7c478bd9Sstevel@tonic-gate }; 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate struct dev_ops dump_ops = { 214*7c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev, */ 215*7c478bd9Sstevel@tonic-gate 0, /* refcnt */ 216*7c478bd9Sstevel@tonic-gate dump_info, /* info */ 217*7c478bd9Sstevel@tonic-gate nulldev, /* identify */ 218*7c478bd9Sstevel@tonic-gate nulldev, /* probe */ 219*7c478bd9Sstevel@tonic-gate dump_attach, /* attach */ 220*7c478bd9Sstevel@tonic-gate dump_detach, /* detach */ 221*7c478bd9Sstevel@tonic-gate nodev, /* reset */ 222*7c478bd9Sstevel@tonic-gate &dump_cb_ops, /* driver operations */ 223*7c478bd9Sstevel@tonic-gate (struct bus_ops *)0 /* bus operations */ 224*7c478bd9Sstevel@tonic-gate }; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 227*7c478bd9Sstevel@tonic-gate &mod_driverops, "crash dump driver %I%", &dump_ops, 228*7c478bd9Sstevel@tonic-gate }; 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 231*7c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modldrv, NULL 232*7c478bd9Sstevel@tonic-gate }; 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate int 235*7c478bd9Sstevel@tonic-gate _init(void) 236*7c478bd9Sstevel@tonic-gate { 237*7c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate int 241*7c478bd9Sstevel@tonic-gate _fini(void) 242*7c478bd9Sstevel@tonic-gate { 243*7c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate int 247*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 248*7c478bd9Sstevel@tonic-gate { 249*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 250*7c478bd9Sstevel@tonic-gate } 251