Index | Thread | Search

From:
Vitaliy Makkoveev <mvs@openbsd.org>
Subject:
Re: cpu perfpolicy
To:
Ted Unangst <tedu@tedunangst.com>
Cc:
tech@openbsd.org
Date:
Mon, 2 Jun 2025 17:37:00 +0300

Download raw body.

Thread
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) {
>