#include "opt_param.h"
#include "opt_maxusers.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/sysctl.h>
#include <vm/pmap.h>
#include <machine/vmparam.h>
#ifndef HZ_DEFAULT
#define HZ_DEFAULT 100
#endif
#define NPROC (20 + 16 * maxusers)
#ifndef NBUF
#define NBUF 0
#endif
#ifndef MAXFILES
#define MAXFILES (maxproc * 16)
#endif
#ifndef MAXPOSIXLOCKSPERUID
#define MAXPOSIXLOCKSPERUID (maxproc * 4)
#endif
static int sysctl_kern_vmm_guest(SYSCTL_HANDLER_ARGS);
int hz;
int stathz;
int profhz;
int ustick;
int nstick;
int maxusers;
int maxproc;
int maxprocperuid;
int maxfiles;
int maxfilesrootres;
int minfilesperproc;
int maxfilesperproc;
int maxfilesperuser;
int maxposixlocksperuid;
int ncallout;
long nbuf;
long nswbuf_mem;
long nswbuf_kva;
long nswbuf_raw;
long maxswzone;
long maxbcache;
enum vmm_guest_type vmm_guest = VMM_GUEST_NONE;
u_quad_t maxtsiz;
u_quad_t dfldsiz;
u_quad_t maxdsiz;
u_quad_t dflssiz;
u_quad_t maxssiz;
u_quad_t sgrowsiz;
u_quad_t maxthrssiz;
SYSCTL_PROC(_kern, OID_AUTO, vmm_guest, CTLFLAG_RD | CTLTYPE_STRING,
NULL, 0, sysctl_kern_vmm_guest, "A",
"Virtual machine guest type");
SYSCTL_QUAD(_kern, OID_AUTO, maxssiz, CTLFLAG_RD, &maxssiz, 0,
"Maximum user stack size");
SYSCTL_QUAD(_kern, OID_AUTO, maxthrssiz, CTLFLAG_RD, &maxthrssiz, 0,
"Nominal threading stack area");
struct buf *swbuf_mem;
struct buf *swbuf_kva;
struct buf *swbuf_raw;
struct vmm_bname {
const char *str;
enum vmm_guest_type type;
};
static struct vmm_bname vmm_bnames[] = {
{ "QEMU", VMM_GUEST_QEMU },
{ "Plex86", VMM_GUEST_PLEX86 },
{ "Bochs", VMM_GUEST_BOCHS },
{ "Xen", VMM_GUEST_XEN },
{ "BHYVE", VMM_GUEST_BHYVE },
{ "Seabios", VMM_GUEST_KVM},
{ NULL, 0 }
};
static struct vmm_bname vmm_pnames[] = {
{ "VMware Virtual Platform", VMM_GUEST_VMWARE },
{ "Virtual Machine", VMM_GUEST_HYPERV },
{ "VirtualBox", VMM_GUEST_VBOX },
{ "Parallels Virtual Platform", VMM_GUEST_PARALLELS },
{ "KVM", VMM_GUEST_KVM },
{ NULL, 0 }
};
static const char *const vmm_guest_sysctl_names[] = {
"none",
"qemu",
"plex86",
"bochs",
"xen",
"bhyve",
"kvm",
"vmware",
"hyperv",
"vbox",
"parallels",
"vkernel",
"nvmm",
"unknown",
NULL
};
CTASSERT(NELEM(vmm_guest_sysctl_names) - 1 == VMM_GUEST_LAST);
char vmm_vendor[16];
SYSCTL_STRING(_kern, OID_AUTO, vmm_vendor, CTLFLAG_RD, vmm_vendor, 0,
"Virtual machine vendor");
enum vmm_guest_type
detect_virtual(void)
{
char *sysenv;
int i;
sysenv = kgetenv("smbios.bios.vendor");
if (sysenv != NULL) {
for (i = 0; vmm_bnames[i].str != NULL; i++)
if (strcmp(sysenv, vmm_bnames[i].str) == 0) {
kfreeenv(sysenv);
return (vmm_bnames[i].type);
}
kfreeenv(sysenv);
}
sysenv = kgetenv("smbios.system.product");
if (sysenv != NULL) {
for (i = 0; vmm_pnames[i].str != NULL; i++)
if (strcmp(sysenv, vmm_pnames[i].str) == 0) {
kfreeenv(sysenv);
return (vmm_pnames[i].type);
}
kfreeenv(sysenv);
}
return (VMM_GUEST_NONE);
}
void
init_param1(void)
{
hz = HZ_DEFAULT;
TUNABLE_INT_FETCH("kern.hz", &hz);
stathz = hz + 1;
TUNABLE_INT_FETCH("kern.stathz", &stathz);
profhz = stathz;
ustick = 1000000 / hz;
nstick = 1000000000 / hz;
ntp_default_tick_delta = howmany(30000000, 60 * hz);
#ifdef VM_SWZONE_SIZE_MAX
maxswzone = VM_SWZONE_SIZE_MAX;
#endif
TUNABLE_LONG_FETCH("kern.maxswzone", &maxswzone);
#ifdef VM_BCACHE_SIZE_MAX
maxbcache = VM_BCACHE_SIZE_MAX;
#endif
TUNABLE_LONG_FETCH("kern.maxbcache", &maxbcache);
maxtsiz = MAXTSIZ;
TUNABLE_QUAD_FETCH("kern.maxtsiz", &maxtsiz);
dfldsiz = DFLDSIZ;
TUNABLE_QUAD_FETCH("kern.dfldsiz", &dfldsiz);
maxdsiz = MAXDSIZ;
TUNABLE_QUAD_FETCH("kern.maxdsiz", &maxdsiz);
dflssiz = DFLSSIZ;
TUNABLE_QUAD_FETCH("kern.dflssiz", &dflssiz);
maxssiz = MAXSSIZ;
TUNABLE_QUAD_FETCH("kern.maxssiz", &maxssiz);
sgrowsiz = SGROWSIZ;
TUNABLE_QUAD_FETCH("kern.sgrowsiz", &sgrowsiz);
maxthrssiz = MAXTHRSSIZ;
TUNABLE_QUAD_FETCH("kern.maxthrssiz", &maxthrssiz);
}
void
init_param2(int physpages)
{
size_t limsize;
limsize = (size_t)physpages * PAGE_SIZE;
if (limsize > KvaSize)
limsize = KvaSize;
if (maxswzone > limsize / 2)
maxswzone = limsize / 2;
limsize /= 1024 * 1024;
maxusers = MAXUSERS;
TUNABLE_INT_FETCH("kern.maxusers", &maxusers);
if (maxusers == 0) {
maxusers = limsize / 8;
if (maxusers < 32)
maxusers = 32;
}
maxproc = NPROC;
TUNABLE_INT_FETCH("kern.maxproc", &maxproc);
if (maxproc < 32)
maxproc = 32;
if (maxproc > limsize * 40)
maxproc = limsize * 40;
maxfiles = MAXFILES;
TUNABLE_INT_FETCH("kern.maxfiles", &maxfiles);
if (maxfiles < 128)
maxfiles = 128;
maxprocperuid = maxproc / 4;
if (maxprocperuid < 128)
maxprocperuid = maxproc / 2;
minfilesperproc = 8;
maxfilesperproc = maxfiles / 4;
maxfilesperuser = maxfilesperproc * 2;
maxfilesrootres = maxfiles / 20;
if (KvaSize <= (vm_offset_t)(1536LL * 1024 * 1024) &&
maxfilesperuser > 20000) {
maxfilesperuser = 20000;
}
maxposixlocksperuid = MAXPOSIXLOCKSPERUID;
TUNABLE_INT_FETCH("kern.maxposixlocksperuid", &maxposixlocksperuid);
nbuf = NBUF;
TUNABLE_LONG_FETCH("kern.nbuf", &nbuf);
ncallout = 16 + maxproc + maxfiles;
if (ncallout > 5*60*hz)
ncallout = 5*60*hz;
TUNABLE_INT_FETCH("kern.ncallout", &ncallout);
}
static int
sysctl_kern_vmm_guest(SYSCTL_HANDLER_ARGS)
{
return (SYSCTL_OUT(req, vmm_guest_sysctl_names[vmm_guest],
strlen(vmm_guest_sysctl_names[vmm_guest])));
}