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 * Copyright 2016 Joyent, Inc.
26 */
27
28/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
29/*	  All Rights Reserved	*/
30
31#include <sys/param.h>
32#include <sys/types.h>
33#include <sys/sysmacros.h>
34#include <sys/systm.h>
35#include <sys/tuneable.h>
36#include <sys/errno.h>
37#include <sys/var.h>
38#include <sys/signal.h>
39#include <sys/time.h>
40#include <sys/sysconfig.h>
41#include <sys/resource.h>
42#include <sys/ulimit.h>
43#include <sys/unistd.h>
44#include <sys/debug.h>
45#include <sys/cpuvar.h>
46#include <sys/mman.h>
47#include <sys/timer.h>
48#include <sys/zone.h>
49#include <sys/vm_usage.h>
50#include <vm/as.h>
51
52extern rctl_hndl_t rc_process_sigqueue;
53
54long
55sysconfig(int which)
56{
57	switch (which) {
58
59	/*
60	 * if it is not handled in mach_sysconfig either
61	 * it must be EINVAL.
62	 */
63	default:
64		return (mach_sysconfig(which)); /* `uname -i`/os */
65
66	case _CONFIG_CLK_TCK:
67		return ((long)hz);	/* clock frequency per second */
68
69	case _CONFIG_PROF_TCK:
70		return ((long)hz);	/* profiling clock freq per sec */
71
72	case _CONFIG_NGROUPS:
73		/*
74		 * Maximum number of supplementary groups.
75		 */
76		return (ngroups_max);
77
78	case _CONFIG_OPEN_FILES:
79		/*
80		 * Maximum number of open files (soft limit).
81		 */
82		{
83			rlim64_t fd_ctl;
84			mutex_enter(&curproc->p_lock);
85			fd_ctl = rctl_enforced_value(
86			    rctlproc_legacy[RLIMIT_NOFILE], curproc->p_rctls,
87			    curproc);
88			mutex_exit(&curproc->p_lock);
89			return ((ulong_t)fd_ctl);
90		}
91
92	case _CONFIG_CHILD_MAX:
93		/*
94		 * Maximum number of processes.
95		 */
96		return (v.v_maxup);
97
98	case _CONFIG_POSIX_VER:
99		return (_POSIX_VERSION); /* current POSIX version */
100
101	case _CONFIG_PAGESIZE:
102		return (PAGESIZE);
103
104	case _CONFIG_XOPEN_VER:
105		return (_XOPEN_VERSION); /* current XOPEN version */
106
107	case _CONFIG_NPROC_CONF:
108		return (zone_ncpus_get(curproc->p_zone));
109
110	case _CONFIG_NPROC_ONLN:
111		return (zone_ncpus_online_get(curproc->p_zone));
112
113	case _CONFIG_NPROC_MAX:
114		return (max_ncpus);
115
116	case _CONFIG_NPROC_NCPU:
117		return (NCPU); /* Private sysconfig for direct NCPU access */
118
119	case _CONFIG_STACK_PROT:
120		return (curproc->p_stkprot & ~PROT_USER);
121
122	case _CONFIG_AIO_LISTIO_MAX:
123		return (_AIO_LISTIO_MAX);
124
125	case _CONFIG_AIO_MAX:
126		return (_AIO_MAX);
127
128	case _CONFIG_AIO_PRIO_DELTA_MAX:
129		return (0);
130
131	case _CONFIG_DELAYTIMER_MAX:
132		return (INT_MAX);
133
134	case _CONFIG_MQ_OPEN_MAX:
135		return (_MQ_OPEN_MAX);
136
137	case _CONFIG_MQ_PRIO_MAX:
138		return (_MQ_PRIO_MAX);
139
140	case _CONFIG_RTSIG_MAX:
141		return (_SIGRTMAX - _SIGRTMIN + 1);
142
143	case _CONFIG_SEM_NSEMS_MAX:
144		return (_SEM_NSEMS_MAX);
145
146	case _CONFIG_SEM_VALUE_MAX:
147		return (_SEM_VALUE_MAX);
148
149	case _CONFIG_SIGQUEUE_MAX:
150		/*
151		 * Maximum number of outstanding queued signals.
152		 */
153		{
154			rlim64_t sigqsz_max;
155			mutex_enter(&curproc->p_lock);
156			sigqsz_max = rctl_enforced_value(rc_process_sigqueue,
157			    curproc->p_rctls, curproc);
158			mutex_exit(&curproc->p_lock);
159			return ((uint_t)sigqsz_max);
160		}
161
162	case _CONFIG_SIGRT_MIN:
163		return (_SIGRTMIN);
164
165	case _CONFIG_SIGRT_MAX:
166		return (_SIGRTMAX);
167
168	case _CONFIG_TIMER_MAX:
169		return (timer_max);
170
171	case _CONFIG_PHYS_PAGES:
172		/*
173		 * If the non-global zone has a phys. memory cap, use that.
174		 * We always report the system-wide value for the global zone,
175		 * even though rcapd can be used on the global zone too.
176		 */
177		if (!INGLOBALZONE(curproc) &&
178		    curproc->p_zone->zone_phys_mcap != 0)
179			return (MIN(btop(curproc->p_zone->zone_phys_mcap),
180			    physinstalled));
181
182		return (physinstalled);
183
184	case _CONFIG_AVPHYS_PAGES:
185		/*
186		 * If the non-global zone has a phys. memory cap, use
187		 * the phys. memory cap - zone's current rss.  We always
188		 * report the system-wide value for the global zone, even
189		 * though rcapd can be used on the global zone too.
190		 */
191		if (!INGLOBALZONE(curproc) &&
192		    curproc->p_zone->zone_phys_mcap != 0) {
193			pgcnt_t cap, rss, free;
194			vmusage_t in_use;
195			size_t cnt = 1;
196
197			cap = btop(curproc->p_zone->zone_phys_mcap);
198			if (cap > physinstalled)
199				return (freemem);
200
201			if (vm_getusage(VMUSAGE_ZONE, 1, &in_use, &cnt,
202			    FKIOCTL) != 0)
203				in_use.vmu_rss_all = 0;
204			rss = btop(in_use.vmu_rss_all);
205			/*
206			 * Because rcapd implements a soft cap, it is possible
207			 * for rss to be temporarily over the cap.
208			 */
209			if (cap > rss)
210				free = cap - rss;
211			else
212				free = 0;
213			return (MIN(free, freemem));
214		}
215
216		return (freemem);
217
218	case _CONFIG_MAXPID:
219		return (maxpid);
220
221	case _CONFIG_CPUID_MAX:
222		return (max_cpuid);
223
224	case _CONFIG_EPHID_MAX:
225		return (MAXEPHUID);
226
227	case _CONFIG_UADDR_MAX:
228		return ((long)(uintptr_t)curproc->p_as->a_userlimit);
229
230	case _CONFIG_SYMLOOP_MAX:
231		return (MAXSYMLINKS);
232	}
233}
234