From: Vitaliy Makkoveev Subject: Re: cpu perfpolicy To: Ted Unangst Cc: tech@openbsd.org Date: Mon, 2 Jun 2025 17:37:00 +0300 On Sun, Jun 01, 2025 at 03:22:59PM -0400, Ted Unangst wrote: > This introduces a helper function for hw.perfpolicy that allows more > machine specific policies to be set. > > On my laptop, there's also a fan policy. This affects performance, but > it's not really related to the existing hw.setperf mechanism. For > example, a "silent" fan setting and "high" CPU setting is reasonable. > Exactly what I want, in fact. > > Fortunately, perfpolicy takes a string, which makes it flexible. > This uses two new optional functions to parse and append the policy. > > hw.perfpolicy=silent,auto > Do we really need to combine them? Why don't have dedicated hw.fanpolicy? > Index: dev/acpi/acpiwmi.c > =================================================================== > RCS file: /home/cvs/src/sys/dev/acpi/acpiwmi.c,v > diff -u -p -r1.5 acpiwmi.c > --- dev/acpi/acpiwmi.c 21 May 2025 02:18:29 -0000 1.5 > +++ dev/acpi/acpiwmi.c 29 May 2025 01:15:42 -0000 > @@ -311,6 +311,40 @@ asus_toggle(struct wmiasus *wh, int devi > asus_dev_set(wh, devid, *val | mask); > } > > +struct wmiasus *wmi_asus_policy_cookie; > +/* xxx the order may vary by machine... */ > +static const char *asus_policies[] = { "standard,", "silent,", "perf," }; > + > +void > +wmi_asus_setpolicy(char *policy) > +{ > + struct wmiasus *wh = wmi_asus_policy_cookie; > + int target = -1; > + > + for (int i = 0; i < nitems(asus_policies); i++) { > + size_t len = strlen(asus_policies[i]); > + if (strncmp(policy, asus_policies[i], len) == 0) { > + target = i; > + memmove(policy, policy + len, strlen(policy + len)+1); > + break; > + } > + } > + if (target != -1) { > + wh->w_perf = target; > + asus_dev_set(wh, wh->w_perfid, wh->w_perf); > + } > +} > + > +void > +wmi_asus_getpolicy(char *policy, size_t len) > +{ > + struct wmiasus *wh = wmi_asus_policy_cookie; > + int target = wh->w_perf; > + > + if (target >= 0 && target < nitems(asus_policies)) > + strlcpy(policy, asus_policies[target], len); > +} > + > static int > wmi_asus_init(struct acpiwmi_softc *sc, struct guidinfo *ginfo) > { > @@ -342,6 +376,13 @@ wmi_asus_init(struct acpiwmi_softc *sc, > res = asus_dev_get(wh, ASUS_DEV_PERF_2); > if (res >= 0) > wh->w_perfid = ASUS_DEV_PERF_2; > + if (wh->w_perfid != 0) { > + extern void (*cpu_setpolicy)(char *); > + extern void (*cpu_getpolicy)(char *, size_t); > + cpu_getpolicy = wmi_asus_getpolicy; > + cpu_setpolicy = wmi_asus_setpolicy; > + wmi_asus_policy_cookie = wh; > + } > // turn on by default > asus_toggle(wh, ASUS_DEV_KBDLIGHT, &wh->w_kbdlight); > > Index: kern/sched_bsd.c > =================================================================== > RCS file: /home/cvs/src/sys/kern/sched_bsd.c,v > diff -u -p -r1.100 sched_bsd.c > --- kern/sched_bsd.c 31 May 2025 06:58:27 -0000 1.100 > +++ kern/sched_bsd.c 1 Jun 2025 07:48:21 -0000 > @@ -541,6 +541,8 @@ schedclock(struct proc *p) > } > > void (*cpu_setperf)(int); > +void (*cpu_setpolicy)(char *); > +void (*cpu_getpolicy)(char *, size_t); > > #define PERFPOL_MANUAL 0 > #define PERFPOL_AUTO 1 > @@ -671,18 +673,22 @@ sysctl_hwperfpolicy(void *oldp, size_t * > if (!cpu_setperf) > return EOPNOTSUPP; > > + policy[0] = 0; > + if (cpu_getpolicy) > + cpu_getpolicy(policy, sizeof(policy)); > + > switch (current_perfpolicy()) { > case PERFPOL_MANUAL: > - strlcpy(policy, "manual", sizeof(policy)); > + strlcat(policy, "manual", sizeof(policy)); > break; > case PERFPOL_AUTO: > - strlcpy(policy, "auto", sizeof(policy)); > + strlcat(policy, "auto", sizeof(policy)); > break; > case PERFPOL_HIGH: > - strlcpy(policy, "high", sizeof(policy)); > + strlcat(policy, "high", sizeof(policy)); > break; > default: > - strlcpy(policy, "unknown", sizeof(policy)); > + strlcat(policy, "unknown", sizeof(policy)); > break; > } > > @@ -692,6 +698,9 @@ sysctl_hwperfpolicy(void *oldp, size_t * > err = sysctl_string(oldp, oldlenp, newp, newlen, policy, sizeof(policy)); > if (err) > return err; > + > + if (cpu_setpolicy) > + cpu_setpolicy(policy); > > policy_on_battery = strchr(policy, ','); > if (policy_on_battery != NULL) { >