Index: sys/kern/subr_param.c =================================================================== --- sys/kern/subr_param.c +++ sys/kern/subr_param.c @@ -80,7 +80,14 @@ #define MAXFILES (40 + 32 * maxusers) #endif -static int sysctl_kern_vm_guest(SYSCTL_HANDLER_ARGS); +struct sysctl_enum_params { + u_int *const value; + u_int last; + char *const names[]; +}; + +static int sysctl_enum_proc(struct sysctl_oid *oidp, void *const _params, + intmax_t arg2, struct sysctl_req *req); int hz; /* system clock's frequency */ int tick; /* usec per tick (1000000 / hz) */ @@ -136,28 +143,31 @@ "Maximum stack size"); SYSCTL_ULONG(_kern, OID_AUTO, sgrowsiz, CTLFLAG_RWTUN | CTLFLAG_NOFETCH, &sgrowsiz, 0, "Amount to grow stack on a stack fault"); -SYSCTL_PROC(_kern, OID_AUTO, vm_guest, - CTLFLAG_RD | CTLTYPE_STRING | CTLFLAG_MPSAFE, NULL, 0, - sysctl_kern_vm_guest, "A", - "Virtual machine guest detected?"); /* - * The elements of this array are ordered based upon the values of the - * corresponding enum VM_GUEST members. + * Parameters for the vm_guest enum */ -static const char *const vm_guest_sysctl_names[] = { - [VM_GUEST_NO] = "none", - [VM_GUEST_VM] = "generic", - [VM_GUEST_XEN] = "xen", - [VM_GUEST_HV] = "hv", - [VM_GUEST_VMWARE] = "vmware", - [VM_GUEST_KVM] = "kvm", - [VM_GUEST_BHYVE] = "bhyve", - [VM_GUEST_VBOX] = "vbox", - [VM_GUEST_PARALLELS] = "parallels", - [VM_LAST] = NULL +static const struct sysctl_enum_params vm_guest_sysctl_params = { + &vm_guest, + VM_LAST, + { + [VM_GUEST_BHYVE] = "bhyve", + [VM_GUEST_HV] = "hv", + [VM_GUEST_KVM] = "kvm", + [VM_GUEST_NO] = "none", + [VM_GUEST_PARALLELS] = "parallels", + [VM_GUEST_VBOX] = "vbox", + [VM_GUEST_VM] = "generic", + [VM_GUEST_VMWARE] = "vmware", + [VM_GUEST_XEN] = "xen", + [VM_LAST] = NULL + } }; -CTASSERT(nitems(vm_guest_sysctl_names) - 1 == VM_LAST); + +SYSCTL_PROC(_kern, OID_AUTO, vm_guest, + CTLFLAG_RD | CTLTYPE_STRING | CTLFLAG_MPSAFE, + __DECONST(void *, &vm_guest_sysctl_params), 0, sysctl_enum_proc, "A", + "Virtual machine guest detected?"); /* * Boot time overrides that are not scaled against main memory @@ -325,10 +335,19 @@ } /* - * Sysctl stringifying handler for kern.vm_guest. + * Generalized sysctl stringifying handler for enums */ static int -sysctl_kern_vm_guest(SYSCTL_HANDLER_ARGS) +sysctl_enum_proc(struct sysctl_oid *oidp, void *const _params, + intmax_t arg2, struct sysctl_req *req) { - return (SYSCTL_OUT_STR(req, vm_guest_sysctl_names[vm_guest])); + const struct sysctl_enum_params *const params = _params; + + if (*params->value >= params->last) + return (ENXIO); + + if (params->names[*params->value] == NULL) + return (0); + + return (SYSCTL_OUT_STR(req, params->names[*params->value])); }