From 0294e0be5821991219b454f4fdc27f570d30a6fd Mon Sep 17 00:00:00 2001 From: deraadt Date: Sat, 30 Oct 2021 23:24:46 +0000 Subject: [PATCH] Change hw.perfpolicy=auto by default, at startup. If the system has AC power connected (default is yes when no driver differentiates) then default to 100% performance. On battery, use the existing auto algorithm (which is admittedly somewhat unrefined). This change overrides the system/BIOS speed and puts OpenBSD in control. As this happens very early during boot, besides speedups in all usage usage patterns, some surprises: unhibernate and sysupgrade times are cut in half. note: on a few architectures, the setperf fn pointer is changed late, and thus the auto algorithm stops timeing out. kettenis and i will look for a solution. in snaps for more than a week. ok kettenis --- sys/dev/acpi/acpi.c | 3 +- sys/dev/acpi/acpiac.c | 6 +++- sys/kern/kern_sysctl.c | 4 ++- sys/kern/sched_bsd.c | 65 ++++++++++++++++++++++++------------------ sys/sys/sysctl.h | 6 ++-- 5 files changed, 52 insertions(+), 32 deletions(-) diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index 1250bc3468c..8e2ac095c6c 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi.c,v 1.399 2021/07/20 00:41:54 mlarkin Exp $ */ +/* $OpenBSD: acpi.c,v 1.400 2021/10/30 23:24:46 deraadt Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert * Copyright (c) 2005 Jordan Hargrave @@ -3556,6 +3556,7 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) case APM_IOC_GETPOWER: /* A/C */ pi->ac_state = APM_AC_UNKNOWN; +// XXX replace with new power code SLIST_FOREACH(ac, &sc->sc_ac, aac_link) { if (ac->aac_softc->sc_ac_stat == PSR_ONLINE) pi->ac_state = APM_AC_ON; diff --git a/sys/dev/acpi/acpiac.c b/sys/dev/acpi/acpiac.c index e2943ea4504..acd932280b5 100644 --- a/sys/dev/acpi/acpiac.c +++ b/sys/dev/acpi/acpiac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpiac.c,v 1.33 2020/06/10 22:26:40 jca Exp $ */ +/* $OpenBSD: acpiac.c,v 1.34 2021/10/30 23:24:47 deraadt Exp $ */ /* * Copyright (c) 2005 Marco Peereboom * @@ -70,6 +70,7 @@ void acpiac_attach(struct device *parent, struct device *self, void *aux) { struct acpiac_softc *sc = (struct acpiac_softc *)self; + extern int hw_power; struct acpi_attach_args *aa = aux; sc->sc_acpi = (struct acpi_softc *)parent; @@ -83,6 +84,7 @@ acpiac_attach(struct device *parent, struct device *self, void *aux) printf("offline\n"); else printf("in unknown state\n"); + hw_power = (sc->sc_ac_stat == PSR_ONLINE); strlcpy(sc->sc_sensdev.xname, DEVNAME(sc), sizeof(sc->sc_sensdev.xname)); @@ -140,6 +142,7 @@ int acpiac_notify(struct aml_node *node, int notify_type, void *arg) { struct acpiac_softc *sc = arg; + extern int hw_power; dnprintf(10, "acpiac_notify: %.2x %s\n", notify_type, DEVNAME(sc)); @@ -159,5 +162,6 @@ acpiac_notify(struct aml_node *node, int notify_type, void *arg) dnprintf(10, "A/C status: %d\n", sc->sc_ac_stat); break; } + hw_power = (sc->sc_ac_stat == PSR_ONLINE); return (0); } diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 320ed09a21f..aacba022fd7 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.395 2021/10/24 00:02:25 jsg Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.396 2021/10/30 23:24:48 deraadt Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -654,6 +654,7 @@ kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, */ char *hw_vendor, *hw_prod, *hw_uuid, *hw_serial, *hw_ver; int allowpowerdown = 1; +int hw_power = 1; /* morally const values reported by sysctl_bounded_arr */ static int byte_order = BYTE_ORDER; @@ -665,6 +666,7 @@ const struct sysctl_bounded_args hw_vars[] = { {HW_BYTEORDER, &byte_order, SYSCTL_INT_READONLY}, {HW_PAGESIZE, &page_size, SYSCTL_INT_READONLY}, {HW_DISKCOUNT, &disk_count, SYSCTL_INT_READONLY}, + {HW_POWER, &hw_power, SYSCTL_INT_READONLY}, }; int diff --git a/sys/kern/sched_bsd.c b/sys/kern/sched_bsd.c index 956ea24ea07..49295484fb0 100644 --- a/sys/kern/sched_bsd.c +++ b/sys/kern/sched_bsd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sched_bsd.c,v 1.69 2021/09/09 18:41:39 mpi Exp $ */ +/* $OpenBSD: sched_bsd.c,v 1.70 2021/10/30 23:24:48 deraadt Exp $ */ /* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */ /*- @@ -65,23 +65,6 @@ struct __mp_lock sched_lock; void schedcpu(void *); uint32_t decay_aftersleep(uint32_t, uint32_t); -void -scheduler_start(void) -{ - static struct timeout schedcpu_to; - - /* - * We avoid polluting the global namespace by keeping the scheduler - * timeouts static in this function. - * We setup the timeout here and kick schedcpu once to make it do - * its job. - */ - timeout_set(&schedcpu_to, schedcpu, &schedcpu_to); - - rrticks_init = hz / 10; - schedcpu(&schedcpu_to); -} - /* * Force switch among equal priority processes every 100ms. */ @@ -532,7 +515,7 @@ void (*cpu_setperf)(int); #define PERFPOL_AUTO 1 #define PERFPOL_HIGH 2 int perflevel = 100; -int perfpolicy = PERFPOL_MANUAL; +int perfpolicy = PERFPOL_AUTO; #ifndef SMALL_KERNEL /* @@ -542,22 +525,30 @@ int perfpolicy = PERFPOL_MANUAL; void setperf_auto(void *); struct timeout setperf_to = TIMEOUT_INITIALIZER(setperf_auto, NULL); +extern int hw_power; void setperf_auto(void *v) { static uint64_t *idleticks, *totalticks; static int downbeats; - - int i, j; - int speedup; + int i, j = 0; + int speedup = 0; CPU_INFO_ITERATOR cii; struct cpu_info *ci; - uint64_t idle, total, allidle, alltotal; + uint64_t idle, total, allidle = 0, alltotal = 0; if (perfpolicy != PERFPOL_AUTO) return; + if (cpu_setperf == NULL) + return; + + if (hw_power) { + speedup = 1; + goto faster; + } + if (!idleticks) if (!(idleticks = mallocarray(ncpusfound, sizeof(*idleticks), M_DEVBUF, M_NOWAIT | M_ZERO))) @@ -569,10 +560,6 @@ setperf_auto(void *v) sizeof(*idleticks) * ncpusfound); return; } - - alltotal = allidle = 0; - j = 0; - speedup = 0; CPU_INFO_FOREACH(cii, ci) { if (!cpu_is_online(ci)) continue; @@ -596,6 +583,7 @@ setperf_auto(void *v) downbeats = 5; if (speedup && perflevel != 100) { +faster: perflevel = 100; cpu_setperf(perflevel); } else if (!speedup && perflevel != 0 && --downbeats <= 0) { @@ -676,3 +664,26 @@ sysctl_hwperfpolicy(void *oldp, size_t *oldlenp, void *newp, size_t newlen) return 0; } #endif + +void +scheduler_start(void) +{ + static struct timeout schedcpu_to; + + /* + * We avoid polluting the global namespace by keeping the scheduler + * timeouts static in this function. + * We setup the timeout here and kick schedcpu once to make it do + * its job. + */ + timeout_set(&schedcpu_to, schedcpu, &schedcpu_to); + + rrticks_init = hz / 10; + schedcpu(&schedcpu_to); + +#ifndef SMALL_KERNEL + if (perfpolicy == PERFPOL_AUTO) + timeout_add_msec(&setperf_to, 200); +#endif +} + diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index afdc0689dee..bc6d79ef6c9 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sysctl.h,v 1.218 2021/05/17 17:54:31 claudio Exp $ */ +/* $OpenBSD: sysctl.h,v 1.219 2021/10/30 23:24:48 deraadt Exp $ */ /* $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $ */ /* @@ -928,7 +928,8 @@ struct kinfo_file { #define HW_PERFPOLICY 23 /* set performance policy */ #define HW_SMT 24 /* int: enable SMT/HT/CMT */ #define HW_NCPUONLINE 25 /* int: number of cpus being used */ -#define HW_MAXID 26 /* number of valid hw ids */ +#define HW_POWER 26 /* int: machine has wall-power */ +#define HW_MAXID 27 /* number of valid hw ids */ #define CTL_HW_NAMES { \ { 0, 0 }, \ @@ -957,6 +958,7 @@ struct kinfo_file { { "perfpolicy", CTLTYPE_STRING }, \ { "smt", CTLTYPE_INT }, \ { "ncpuonline", CTLTYPE_INT }, \ + { "power", CTLTYPE_INT }, \ } /* -- 2.20.1