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  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  27 
  28 #include <vm/anon.h>
  29 #include <sys/systm.h>
  30 #include <sys/sysmacros.h>
  31 #include <sys/zone.h>
  32 #include <sys/time.h>
  33 
  34 struct lx_sysinfo {
  35         int32_t si_uptime;      /* Seconds since boot */
  36         uint32_t si_loads[3];   /* 1, 5, and 15 minute avg runq length */
  37         uint32_t si_totalram;   /* Total memory size */
  38         uint32_t si_freeram;    /* Available memory */
  39         uint32_t si_sharedram;  /* Shared memory */
  40         uint32_t si_bufferram;  /* Buffer memory */
  41         uint32_t si_totalswap;  /* Total swap space */
  42         uint32_t si_freeswap;   /* Avail swap space */
  43         uint16_t si_procs;      /* Process count */
  44         uint32_t si_totalhigh;  /* High memory size */
  45         uint32_t si_freehigh;   /* Avail high memory */
  46         uint32_t si_mem_unit;   /* Unit size of memory fields */
  47 };
  48 
  49 long
  50 lx_sysinfo(struct lx_sysinfo *sip)
  51 {
  52         struct lx_sysinfo si;
  53         hrtime_t birthtime;
  54         zone_t *zone = curthread->t_procp->p_zone;
  55         proc_t *init_proc;
  56 
  57         /*
  58          * We don't record the time a zone was booted, so we use the
  59          * birthtime of that zone's init process instead.
  60          */
  61         mutex_enter(&pidlock);
  62         init_proc = prfind(zone->zone_proc_initpid);
  63         if (init_proc != NULL)
  64                 birthtime = init_proc->p_mstart;
  65         else
  66                 birthtime = p0.p_mstart;
  67         mutex_exit(&pidlock);
  68         si.si_uptime = (gethrtime() - birthtime) / NANOSEC;
  69 
  70         /*
  71          * We scale down the load in avenrun to allow larger load averages
  72          * to fit in 32 bits.  Linux doesn't, so we remove the scaling
  73          * here.
  74          */
  75         si.si_loads[0] = avenrun[0] << FSHIFT;
  76         si.si_loads[1] = avenrun[1] << FSHIFT;
  77         si.si_loads[2] = avenrun[2] << FSHIFT;
  78 
  79         /*
  80          * In linux each thread looks like a process, so we conflate the
  81          * two in this stat as well.
  82          */
  83         si.si_procs = (int32_t)zone->zone_nlwps;
  84 
  85         /*
  86          * If the maximum memory stat is less than 1^20 pages (i.e. 4GB),
  87          * then we report the result in bytes.  Otherwise we use pages.
  88          * Once we start supporting >1TB x86 systems, we'll need a third
  89          * option.
  90          */
  91         if (MAX(physmem, k_anoninfo.ani_max) < 1024 * 1024) {
  92                 si.si_totalram = physmem * PAGESIZE;
  93                 si.si_freeram = freemem * PAGESIZE;
  94                 si.si_totalswap = k_anoninfo.ani_max * PAGESIZE;
  95                 si.si_freeswap = k_anoninfo.ani_free * PAGESIZE;
  96                 si.si_mem_unit = 1;
  97         } else {
  98                 si.si_totalram = physmem;
  99                 si.si_freeram = freemem;
 100                 si.si_totalswap = k_anoninfo.ani_max;
 101                 si.si_freeswap = k_anoninfo.ani_free;
 102                 si.si_mem_unit = PAGESIZE;
 103         }
 104         si.si_bufferram = 0;
 105         si.si_sharedram = 0;
 106 
 107         /*
 108          * These two stats refer to high physical memory.  If an
 109          * application running in a Linux zone cares about this, then
 110          * either it or we are broken.
 111          */
 112         si.si_totalhigh = 0;
 113         si.si_freehigh = 0;
 114 
 115         if (copyout(&si, sip, sizeof (si)) != 0)
 116                 return (set_errno(EFAULT));
 117         return (0);
 118 }