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 (c) 1983, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2012 Milan Jurik. All rights reserved.
  24  */
  25 
  26 #include <sys/types.h>
  27 #include <sys/time.h>
  28 #include <sys/param.h>
  29 #include <sys/systm.h>
  30 #include <sys/signal.h>
  31 #include <sys/sysmacros.h>
  32 #include <sys/cmn_err.h>
  33 #include <sys/user.h>
  34 #include <sys/proc.h>
  35 #include <sys/task.h>
  36 #include <sys/project.h>
  37 #include <sys/klwp.h>
  38 #include <sys/vnode.h>
  39 #include <sys/file.h>
  40 #include <sys/fcntl.h>
  41 #include <sys/flock.h>
  42 #include <sys/var.h>
  43 #include <sys/stream.h>
  44 #include <sys/strsubr.h>
  45 #include <sys/conf.h>
  46 #include <sys/class.h>
  47 #include <sys/ts.h>
  48 #include <sys/rt.h>
  49 #include <sys/exec.h>
  50 #include <sys/exechdr.h>
  51 #include <sys/buf.h>
  52 #include <sys/resource.h>
  53 #include <vm/seg.h>
  54 #include <vm/pvn.h>
  55 #include <vm/seg_kmem.h>
  56 #include <sys/vmparam.h>
  57 #include <sys/machparam.h>
  58 #include <sys/utsname.h>
  59 #include <sys/kmem.h>
  60 #include <sys/stack.h>
  61 #include <sys/modctl.h>
  62 #include <sys/fdbuffer.h>
  63 #include <sys/cyclic_impl.h>
  64 #include <sys/disp.h>
  65 #include <sys/tuneable.h>
  66 #include <sys/systeminfo.h>
  67 
  68 #include <sys/vmem.h>
  69 #include <sys/clock.h>
  70 #include <sys/clock_impl.h>
  71 #include <sys/serializer.h>
  72 
  73 /*
  74  * The following few lines describe generic things that must be compiled
  75  * into the booted executable (unix) rather than genunix or any other
  76  * module because they're required by crash dump readers, etc.
  77  */
  78 struct modctl modules;          /* head of linked list of modules */
  79 char *default_path;             /* default module loading path */
  80 struct swapinfo *swapinfo;      /* protected by the swapinfo_lock */
  81 proc_t *practive;               /* active process list */
  82 uint_t nproc;                   /* current number of processes */
  83 proc_t p0;                      /* process 0 */
  84 struct plock p0lock;            /* p0's p_lock */
  85 klwp_t lwp0;                    /* t0's lwp */
  86 task_t *task0p;                 /* task 0 */
  87 kproject_t *proj0p;             /* location of project 0 */
  88 
  89 /*
  90  * The following are "implementation architecture" dependent constants made
  91  * available here in the form of initialized data for use by "implementation
  92  * architecture" independent modules. See machparam.h.
  93  */
  94 const unsigned long     _pagesize       = (unsigned long)PAGESIZE;
  95 const unsigned int      _pageshift      = (unsigned int)PAGESHIFT;
  96 const unsigned long     _pageoffset     = (unsigned long)PAGEOFFSET;
  97 /*
  98  * XXX - This value pagemask has to be a 64bit size because
  99  * large file support uses this mask on offsets which are 64 bit size.
 100  * using unsigned leaves the higher 32 bits value as zero thus
 101  * corrupting offset calculations in the file system and VM.
 102  */
 103 const u_longlong_t      _pagemask       = (u_longlong_t)PAGEMASK;
 104 const unsigned long     _mmu_pagesize   = (unsigned long)MMU_PAGESIZE;
 105 const unsigned int      _mmu_pageshift  = (unsigned int)MMU_PAGESHIFT;
 106 const unsigned long     _mmu_pageoffset = (unsigned long)MMU_PAGEOFFSET;
 107 const unsigned long     _mmu_pagemask   = (unsigned long)MMU_PAGEMASK;
 108 uintptr_t               _kernelbase     = (uintptr_t)KERNELBASE;
 109 uintptr_t               _userlimit      = (uintptr_t)USERLIMIT;
 110 uintptr_t               _userlimit32    = (uintptr_t)USERLIMIT32;
 111 const uintptr_t         _argsbase       = (uintptr_t)ARGSBASE;
 112 const unsigned int      _diskrpm        = (unsigned int)DISKRPM;
 113 const unsigned long     _pgthresh       = (unsigned long)PGTHRESH;
 114 const unsigned int      _maxslp         = (unsigned int)MAXSLP;
 115 const unsigned long     _maxhandspreadpages = (unsigned long)MAXHANDSPREADPAGES;
 116 const int               _ncpu           = (int)NCPU;
 117 const int               _ncpu_log2      = (int)NCPU_LOG2;
 118 const int               _ncpu_p2        = (int)NCPU_P2;
 119 const unsigned long     _defaultstksz   = (unsigned long)DEFAULTSTKSZ;
 120 const unsigned int      _nbpg           = (unsigned int)MMU_PAGESIZE;
 121 
 122 /*
 123  * System parameter formulae.
 124  *
 125  * This file is copied into each directory where we compile
 126  * the kernel; it should be modified there to suit local taste
 127  * if necessary.
 128  */
 129 
 130 /*
 131  * Default hz is 100, but if we set hires_tick we get higher resolution
 132  * clock behavior (currently defined to be 1000 hz).  Higher values seem
 133  * to work, but are not supported.
 134  *
 135  * If we do decide to play with higher values, remember that hz should
 136  * satisfy the following constraints to avoid integer round-off problems:
 137  *
 138  * (1) hz should be in the range 100 <= hz <= MICROSEC.  If hz exceeds
 139  *     MICROSEC, usec_per_tick will be zero and lots of stuff will break.
 140  *     Similarly, if hz < 100 then hz / 100 == 0 and stuff will break.
 141  *
 142  * (2) If hz <= 1000, it should be both a multiple of 100 and a
 143  *      divisor of 1000.
 144  *
 145  * (3) If hz > 1000, it should be both a multiple of 1000 and a
 146  *      divisor of MICROSEC.
 147  *
 148  * Thus the only reasonable values of hz (i.e. the values that won't
 149  * cause roundoff error) are: 100, 200, 500, 1000, 2000, 4000, 5000,
 150  * 8000, 10000, 20000, 25000, 40000, 50000, 100000, 125000, 200000,
 151  * 250000, 500000, 1000000.  As of this writing (1996) a clock rate
 152  * of more than about 10 kHz seems utterly ridiculous, although
 153  * this observation will no doubt seem quaintly amusing one day.
 154  */
 155 #define HIRES_HZ_DEFAULT        1000
 156 
 157 int hz = HZ_DEFAULT;
 158 int hires_hz = HIRES_HZ_DEFAULT;
 159 
 160 int hires_tick = 0;
 161 int cpu_decay_factor = 10;      /* this is no longer tied to clock */
 162 int max_hres_adj;       /* maximum adjustment of hrtime per tick */
 163 int tick_per_msec;      /* clock ticks per millisecond (zero if hz < 1000) */
 164 
 165 /*
 166  * Milliseconds, Microseconds, and Nanoseconds per clock tick
 167  *
 168  * Note:
 169  *  msec_per_tick is zero if hz > 1000
 170  */
 171 int msec_per_tick;
 172 int usec_per_tick;
 173 int nsec_per_tick;
 174 
 175 /*
 176  * Time Resolution values. These are defined in condvar.h and initialized in
 177  * param_init(). Consumers of cv_reltimedwait() and cv_reltimedwait_sig()
 178  * need to specify how accurate the timeout argument should be through
 179  * one of these values. The intention is to allow the underlying implementation
 180  * to anticipate or defer the expiration of timeouts, preventing unnecessary
 181  * wakeups by batch processing similarly expiring events.
 182  */
 183 time_res_t time_res[TR_COUNT];
 184 
 185 /*
 186  * Setting "snooping" to a non-zero value will cause a deadman panic if
 187  * snoop_interval microseconds elapse without lbolt increasing.  The default
 188  * snoop_interval is 50 seconds.
 189  */
 190 #define SNOOP_INTERVAL_MIN      (MICROSEC)
 191 #define SNOOP_INTERVAL_DEFAULT  (50 * MICROSEC)
 192 
 193 int snooping = 0;
 194 uint_t snoop_interval = SNOOP_INTERVAL_DEFAULT;
 195 
 196 /*
 197  * Tables of initialization functions, called from main().
 198  */
 199 
 200 extern void system_taskq_init(void);
 201 extern void binit(void);
 202 extern void space_init(void);
 203 extern void dnlc_init(void);
 204 extern void vfsinit(void);
 205 extern void finit(void);
 206 extern void strinit(void);
 207 extern void flk_init(void);
 208 extern void ftrace_init(void);
 209 extern void softcall_init(void);
 210 extern void ttyinit(void);
 211 extern void schedctl_init(void);
 212 extern void deadman_init(void);
 213 extern void clock_timer_init(void);
 214 extern void clock_realtime_init(void);
 215 extern void clock_highres_init(void);
 216 extern void clock_tick_mp_init(void);
 217 extern void cu_init(void);
 218 extern void callout_mp_init(void);
 219 extern void cpu_seq_tbl_init(void);
 220 
 221 void    (*init_tbl[])(void) = {
 222         system_taskq_init,
 223         binit,
 224         space_init,
 225         dnlc_init,
 226         vfsinit,
 227         finit,
 228         strinit,
 229         serializer_init,
 230         softcall_init,
 231         ttyinit,
 232         as_init,
 233         pvn_init,
 234         anon_init,
 235         segvn_init,
 236         flk_init,
 237         cpu_seq_tbl_init,
 238         schedctl_init,
 239         fdb_init,
 240         deadman_init,
 241         clock_timer_init,
 242         clock_realtime_init,
 243         clock_highres_init,
 244         0
 245 };
 246 
 247 
 248 #if defined(__sparc)
 249         extern void siron_mp_init();
 250 #endif
 251 
 252 /*
 253  * Any per cpu resources should be initialized via
 254  * an entry in mp_init_tbl().
 255  */
 256 void    (*mp_init_tbl[])(void) = {
 257         ftrace_init,
 258         cyclic_mp_init,
 259 #if defined(__sparc)
 260         siron_mp_init,
 261 #endif
 262         clock_tick_mp_init,
 263         cu_init,
 264         callout_mp_init,
 265         0
 266 };
 267 
 268 int maxusers;           /* kitchen-sink knob for dynamic configuration */
 269 
 270 /*
 271  * pidmax -- highest pid value assigned by the system
 272  * Settable in /etc/system
 273  */
 274 int pidmax = DEFAULT_MAXPID;
 275 
 276 /*
 277  * jump_pid - if set, this value is where pid numbers should start
 278  * after the first few system pids (0-3) are used.  If 0, pids are
 279  * chosen in the usual way. This variable can be used to quickly
 280  * create large pids (by setting it to 100000, for example). pids
 281  * less than this value will never be chosen.
 282  */
 283 pid_t jump_pid = DEFAULT_JUMPPID;
 284 
 285 /*
 286  * autoup -- used in struct var for dynamic config of the age a delayed-write
 287  * buffer must be in seconds before bdflush will write it out.
 288  */
 289 #define DEFAULT_AUTOUP  30
 290 int autoup = DEFAULT_AUTOUP;
 291 
 292 /*
 293  * bufhwm -- tuneable variable for struct var for v_bufhwm.
 294  * high water mark for buffer cache mem usage in units of K bytes.
 295  *
 296  * bufhwm_pct -- ditto, but given in % of physmem.
 297  */
 298 int bufhwm = 0;
 299 int bufhwm_pct = 0;
 300 
 301 /*
 302  * Process table.
 303  */
 304 int maxpid;
 305 int max_nprocs;         /* set in param_init() */
 306 int maxuprc;            /* set in param_init() */
 307 int reserved_procs;
 308 int nthread = 1;
 309 
 310 /*
 311  * UFS tunables
 312  */
 313 int ufs_ninode;         /* declared here due to backwards compatibility */
 314 int ndquot;             /* declared here due to backwards compatibility */
 315 
 316 /*
 317  * Exec switch table. This is used by the generic exec module
 318  * to switch out to the desired executable type, based on the
 319  * magic number. The currently supported types are ELF, a.out
 320  * (both NMAGIC and ZMAGIC), interpreter (#!) files,
 321  * and Java executables.
 322  */
 323 /*
 324  * Magic numbers
 325  */
 326 short elfmagic = 0x7f45;
 327 short intpmagic = 0x2321;
 328 short jmagic = 0x504b;
 329 
 330 #if defined(__sparc)
 331 short aout_nmagic = NMAGIC;
 332 short aout_zmagic = ZMAGIC;
 333 short aout_omagic = OMAGIC;
 334 #endif
 335 short nomagic = 0;
 336 
 337 /*
 338  * Magic strings
 339  */
 340 #define ELF32MAGIC_STRING       "\x7f""ELF\x1"
 341 #define ELF64MAGIC_STRING       "\x7f""ELF\x2"
 342 #define INTPMAGIC_STRING        "#!"
 343 #define JAVAMAGIC_STRING        "PK\003\004"
 344 #define AOUT_OMAGIC_STRING      "\x1""\x07"     /* 0407 */
 345 #define AOUT_NMAGIC_STRING      "\x1""\x08"     /* 0410 */
 346 #define AOUT_ZMAGIC_STRING      "\x1""\x0b"     /* 0413 */
 347 #define NOMAGIC_STRING          ""
 348 
 349 #define SHBIN_CNTL(x)   ((x)&037)
 350 #define SHBINMAGIC_STRING {SHBIN_CNTL('k'), SHBIN_CNTL('s'), SHBIN_CNTL('h'), 0}
 351 #define SHBINMAGIC_LEN  4
 352 
 353 char elf32magicstr[] = ELF32MAGIC_STRING;
 354 char elf64magicstr[] = ELF64MAGIC_STRING;
 355 char intpmagicstr[] = INTPMAGIC_STRING;
 356 char shbinmagicstr[] = SHBINMAGIC_STRING;
 357 char javamagicstr[] = JAVAMAGIC_STRING;
 358 #if defined(__sparc)
 359 char aout_nmagicstr[] = AOUT_NMAGIC_STRING;
 360 char aout_zmagicstr[] = AOUT_ZMAGIC_STRING;
 361 char aout_omagicstr[] = AOUT_OMAGIC_STRING;
 362 #endif
 363 char nomagicstr[] = NOMAGIC_STRING;
 364 
 365 char *execswnames[] = {
 366         "elfexec",      /* Elf32 */
 367 #ifdef _LP64
 368         "elfexec",      /* Elf64 */
 369 #endif
 370         "intpexec",
 371         "shbinexec",
 372         "javaexec",
 373 #if defined(__sparc)
 374         "aoutexec",
 375         "aoutexec",
 376         "aoutexec",
 377 #endif
 378         NULL,
 379         NULL,
 380         NULL
 381 };
 382 
 383 struct execsw execsw[] = {
 384         { elf32magicstr, 0, 5, NULL, NULL, NULL },
 385 #ifdef _LP64
 386         { elf64magicstr, 0, 5, NULL, NULL, NULL },
 387 #endif
 388         { intpmagicstr, 0, 2, NULL, NULL, NULL },
 389         { shbinmagicstr, 0, SHBINMAGIC_LEN, NULL, NULL, NULL },
 390         { javamagicstr, 0, 4, NULL, NULL, NULL },
 391 #if defined(__sparc)
 392         { aout_zmagicstr, 2, 2, NULL, NULL, NULL },
 393         { aout_nmagicstr, 2, 2, NULL, NULL, NULL },
 394         { aout_omagicstr, 2, 2, NULL, NULL, NULL },
 395 #endif
 396         { nomagicstr, 0, 0, NULL, NULL, NULL },
 397         { nomagicstr, 0, 0, NULL, NULL, NULL },
 398         { nomagicstr, 0, 0, NULL, NULL, NULL },
 399         { nomagicstr, 0, 0, NULL, NULL, NULL }
 400 };
 401 int nexectype = sizeof (execsw) / sizeof (execsw[0]);   /* # of exec types */
 402 kmutex_t execsw_lock;   /* Used for allocation of execsw entries */
 403 
 404 /*
 405  * symbols added to make changing max-file-descriptors
 406  * simple via /etc/system
 407  */
 408 #define RLIM_FD_CUR 0x100
 409 #define RLIM_FD_MAX 0x10000
 410 
 411 uint_t rlim_fd_cur = RLIM_FD_CUR;
 412 uint_t rlim_fd_max = RLIM_FD_MAX;
 413 
 414 /*
 415  * (Default resource limits were formerly declared here, but are now provided by
 416  * the more general resource controls framework.)
 417  */
 418 
 419 /*
 420  * STREAMS tunables
 421  */
 422 int     nstrpush = 9;           /* maximum # of modules/drivers on a stream */
 423 ssize_t strctlsz = 1024;        /* maximum size of user-generated M_PROTO */
 424 ssize_t strmsgsz = 0x10000;     /* maximum size of user-generated M_DATA */
 425                                 /* for `strmsgsz', zero means unlimited */
 426 /*
 427  * Filesystem tunables
 428  */
 429 int     rstchown = 1;           /* POSIX_CHOWN_RESTRICTED is enabled */
 430 int     ngroups_max = NGROUPS_MAX_DEFAULT;
 431 
 432 /*
 433  * generic scheduling stuff
 434  *
 435  * Configurable parameters for RT and TS are in the respective
 436  * scheduling class modules.
 437  */
 438 
 439 pri_t maxclsyspri = MAXCLSYSPRI;
 440 pri_t minclsyspri = MINCLSYSPRI;
 441 char sys_name[] = "SYS";
 442 
 443 extern pri_t sys_init(id_t, int, classfuncs_t **);
 444 extern classfuncs_t sys_classfuncs;
 445 
 446 sclass_t sclass[] = {
 447         { "SYS",        sys_init,       &sys_classfuncs, STATIC_SCHED, 0 },
 448         { "",   NULL,   NULL,   NULL, 0 },
 449         { "",   NULL,   NULL,   NULL, 0 },
 450         { "",   NULL,   NULL,   NULL, 0 },
 451         { "",   NULL,   NULL,   NULL, 0 },
 452         { "",   NULL,   NULL,   NULL, 0 },
 453         { "",   NULL,   NULL,   NULL, 0 },
 454         { "",   NULL,   NULL,   NULL, 0 },
 455         { "",   NULL,   NULL,   NULL, 0 },
 456         { "",   NULL,   NULL,   NULL, 0 }
 457 };
 458 
 459 int loaded_classes = 1;         /* for loaded classes */
 460 kmutex_t class_lock;            /* lock for class[] */
 461 
 462 int nclass = sizeof (sclass) / sizeof (sclass_t);
 463 char initcls[] = "TS";
 464 char *defaultclass = initcls;
 465 
 466 /*
 467  * Tunable system parameters.
 468  */
 469 
 470 /*
 471  * The integers tune_* are done this way so that the tune
 472  * data structure may be "tuned" if necessary from the /etc/system
 473  * file. The tune data structure is initialized in param_init();
 474  */
 475 
 476 tune_t tune;
 477 
 478 /*
 479  * If freemem < t_getpgslow, then start to steal pages from processes.
 480  */
 481 int tune_t_gpgslo = 25;
 482 
 483 /*
 484  * Rate at which fsflush is run, in seconds.
 485  */
 486 #define DEFAULT_TUNE_T_FSFLUSHR 1
 487 int tune_t_fsflushr = DEFAULT_TUNE_T_FSFLUSHR;
 488 
 489 /*
 490  * The minimum available resident (not swappable) memory to maintain
 491  * in order to avoid deadlock.  In pages.
 492  */
 493 int tune_t_minarmem = 25;
 494 
 495 /*
 496  * The minimum available swappable memory to maintain in order to avoid
 497  * deadlock.  In pages.
 498  */
 499 int tune_t_minasmem = 25;
 500 
 501 int tune_t_flckrec = 512;       /* max # of active frlocks */
 502 
 503 /*
 504  * Number of currently available pages that cannot be 'locked'
 505  * This is set in init_pages_pp_maximum, and must be initialized
 506  * to zero here to detect an override in /etc/system
 507  */
 508 pgcnt_t pages_pp_maximum = 0;
 509 
 510 int boothowto;                  /* boot flags passed to kernel */
 511 struct var v;                   /* System Configuration Information */
 512 
 513 /*
 514  * System Configuration Information
 515  */
 516 
 517 /*
 518  * The physical system's host identifier, expressed as a decimal string.
 519  * Code should only directly access this value when writing to it (setting the
 520  * physical system's host identifier).  Code that reads the physical system's
 521  * host identifier should use zone_get_hostid(NULL) instead.
 522  */
 523 char hw_serial[HW_HOSTID_LEN] = "0";
 524 
 525 #if defined(__sparc)
 526 
 527 /*
 528  * On sparc machines, read hw_serial from the firmware at boot time
 529  * and simply assert Oracle is the hardware provider.
 530  */
 531 char architecture[] = "sparcv9";
 532 char architecture_32[] = "sparc";
 533 char hw_provider[] = "Oracle Corporation";
 534 
 535 #elif defined(__i386)
 536 
 537 char architecture[] = "i386";
 538 char architecture_32[] = "i386";
 539 char hw_provider[SYS_NMLN] = "";
 540 
 541 #elif defined(__amd64)
 542 
 543 char architecture[] = "amd64";
 544 char architecture_32[] = "i386";
 545 char hw_provider[SYS_NMLN] = "";
 546 
 547 #else
 548 #error "unknown processor architecture"
 549 #endif
 550 
 551 char srpc_domain[SYS_NMLN] = "";
 552 char platform[SYS_NMLN] = "";   /* read from the devinfo root node */
 553 
 554 /* Initialize isa_list */
 555 char *isa_list = architecture;
 556 
 557 static pgcnt_t original_physmem = 0;
 558 
 559 #define MIN_DEFAULT_MAXUSERS    8u
 560 #define MAX_DEFAULT_MAXUSERS    2048u
 561 #define MAX_MAXUSERS            4096u
 562 
 563 void
 564 param_preset(void)
 565 {
 566         original_physmem = physmem;
 567 }
 568 
 569 void
 570 param_calc(int platform_max_nprocs)
 571 {
 572         /*
 573          * Default to about one "user" per megabyte, taking into
 574          * account both physical and virtual constraints.
 575          * Note: 2^20 is a meg; shifting right by (20 - PAGESHIFT)
 576          * converts pages to megs without integer overflow.
 577          */
 578 #if defined(__sparc)
 579         if (physmem > original_physmem) {
 580                 physmem = original_physmem;
 581                 cmn_err(CE_NOTE, "physmem limited to %ld", physmem);
 582         }
 583 #endif
 584         if (maxusers == 0) {
 585                 pgcnt_t physmegs = physmem >> (20 - PAGESHIFT);
 586                 pgcnt_t virtmegs = vmem_size(heap_arena, VMEM_FREE) >> 20;
 587                 maxusers = MIN(MAX(MIN(physmegs, virtmegs),
 588                     MIN_DEFAULT_MAXUSERS), MAX_DEFAULT_MAXUSERS);
 589         }
 590         if (maxusers > MAX_MAXUSERS) {
 591                 maxusers = MAX_MAXUSERS;
 592                 cmn_err(CE_NOTE, "maxusers limited to %d", MAX_MAXUSERS);
 593         }
 594 
 595         if (ngroups_max > NGROUPS_MAX_DEFAULT)
 596                 cmn_err(CE_WARN, "ngroups_max of %d > %d, NFS AUTH_SYS will"
 597                     " not work properly", ngroups_max, NGROUPS_MAX_DEFAULT);
 598 
 599 #ifdef DEBUG
 600         /*
 601          * The purpose of maxusers is to prevent memory overcommit.
 602          * DEBUG kernels take more space, so reduce maxusers a bit.
 603          */
 604         maxusers = (3 * maxusers) / 4;
 605 #endif
 606 
 607         /*
 608          * We need to dynamically change any variables now so that
 609          * the setting of maxusers and pidmax propagate to the other
 610          * variables that are dependent on them.
 611          */
 612         if (reserved_procs == 0)
 613                 reserved_procs = 5;
 614         if (pidmax < reserved_procs || pidmax > MAX_MAXPID)
 615                 maxpid = MAX_MAXPID;
 616         else
 617                 maxpid = pidmax;
 618 
 619         /*
 620          * This allows platform-dependent code to constrain the maximum
 621          * number of processes allowed in case there are e.g. VM limitations
 622          * with how many contexts are available.
 623          */
 624         if (max_nprocs == 0)
 625                 max_nprocs = (10 + 16 * maxusers);
 626         if (platform_max_nprocs > 0 && max_nprocs > platform_max_nprocs)
 627                 max_nprocs = platform_max_nprocs;
 628         if (max_nprocs > maxpid)
 629                 max_nprocs = maxpid;
 630 
 631         if (maxuprc == 0)
 632                 maxuprc = (max_nprocs - reserved_procs);
 633 }
 634 
 635 void
 636 param_init(void)
 637 {
 638         /*
 639          * Set each individual element of struct var v to be the
 640          * default value. This is done this way
 641          * so that a user can set the assigned integer value in the
 642          * /etc/system file *IF* tuning is needed.
 643          */
 644         v.v_proc = max_nprocs;  /* v_proc - max # of processes system wide */
 645         v.v_maxupttl = max_nprocs - reserved_procs;
 646         v.v_maxsyspri = (int)maxclsyspri;  /* max global pri for sysclass */
 647         v.v_maxup = MIN(maxuprc, v.v_maxupttl); /* max procs per user */
 648         v.v_autoup = autoup;    /* v_autoup - delay for delayed writes */
 649 
 650         /*
 651          * Set each individual element of struct tune to be the
 652          * default value. Each struct element This is done this way
 653          *  so that a user can set the assigned integer value in the
 654          * /etc/system file *IF* tuning is needed.
 655          */
 656         tune.t_gpgslo = tune_t_gpgslo;
 657         tune.t_fsflushr = tune_t_fsflushr;
 658         tune.t_minarmem = tune_t_minarmem;
 659         tune.t_minasmem = tune_t_minasmem;
 660         tune.t_flckrec = tune_t_flckrec;
 661 
 662         /*
 663          * Initialization for file descriptors to correct mistaken settings in
 664          * /etc/system.  Initialization of limits performed by resource control
 665          * system.
 666          */
 667         if (rlim_fd_cur > rlim_fd_max)
 668                 rlim_fd_cur = rlim_fd_max;
 669 
 670         /*
 671          * calculations needed if hz was set in /etc/system
 672          */
 673         if (hires_tick)
 674                 hz = hires_hz;
 675 
 676         tick_per_msec = hz / MILLISEC;
 677         msec_per_tick = MILLISEC / hz;
 678         usec_per_tick = MICROSEC / hz;
 679         nsec_per_tick = NANOSEC / hz;
 680         max_hres_adj = nsec_per_tick >> ADJ_SHIFT;
 681 
 682         /*
 683          * Consumers of relative timedwait functions must specify how accurately
 684          * the given timeout must expire. This is currently TR_CLOCK_TICK for
 685          * the vast majority of consumers, but nsec_per_tick becomes an
 686          * artificial value in a tickless world. Each caller of such routines
 687          * should re-evaluate their usage and specify the appropriate
 688          * resolution.
 689          */
 690         time_res[TR_NANOSEC] = NANOSEC / NANOSEC;
 691         time_res[TR_MICROSEC] = NANOSEC / MICROSEC;
 692         time_res[TR_MILLISEC] = NANOSEC / MILLISEC;
 693         time_res[TR_SEC] = NANOSEC / SEC;
 694         time_res[TR_CLOCK_TICK] = nsec_per_tick;
 695 }
 696 
 697 /*
 698  * Validate tuneable parameters following /etc/system processing,
 699  * but prior to param_init().
 700  */
 701 void
 702 param_check(void)
 703 {
 704 #if defined(__x86)
 705         if (physmem != original_physmem) {
 706                 cmn_err(CE_NOTE, "physmem cannot be modified to 0x%lx"
 707                     " via /etc/system. Please use eeprom(1M) instead.",
 708                     physmem);
 709                 physmem = original_physmem;
 710         }
 711 #endif
 712         if (ngroups_max < NGROUPS_UMIN)
 713                 ngroups_max = NGROUPS_UMIN;
 714         if (ngroups_max > NGROUPS_UMAX)
 715                 ngroups_max = NGROUPS_UMAX;
 716 
 717         /* If we have many groups then the ucred proto message also grows. */
 718         if (ngroups_max > NGROUPS_OLDMAX &&
 719             strctlsz < (ngroups_max - NGROUPS_OLDMAX) * sizeof (gid_t) + 1024) {
 720                 strctlsz = (ngroups_max - NGROUPS_OLDMAX) * sizeof (gid_t) +
 721                     1024;
 722         }
 723 
 724         if (autoup <= 0) {
 725                 autoup = DEFAULT_AUTOUP;
 726                 cmn_err(CE_WARN, "autoup <= 0; defaulting to %d", autoup);
 727         }
 728 
 729         if (tune_t_fsflushr <= 0) {
 730                 tune_t_fsflushr = DEFAULT_TUNE_T_FSFLUSHR;
 731                 cmn_err(CE_WARN, "tune_t_fsflushr <= 0; defaulting to %d",
 732                     tune_t_fsflushr);
 733         }
 734 
 735         if (jump_pid < 0 || jump_pid >= pidmax) {
 736                 jump_pid = 0;
 737                 cmn_err(CE_WARN, "jump_pid < 0 or >= pidmax; ignored");
 738         }
 739 
 740         if (snoop_interval < SNOOP_INTERVAL_MIN) {
 741                 snoop_interval = SNOOP_INTERVAL_DEFAULT;
 742                 cmn_err(CE_WARN, "snoop_interval < minimum (%d); defaulting"
 743                     " to %d", SNOOP_INTERVAL_MIN, SNOOP_INTERVAL_DEFAULT);
 744         }
 745 }