I can test it this weekend. I have a Thinkpad T420. On Fri, Jun 28, 2019 at 04:46:02PM +0200, Benjamin Baier wrote: > On Mon, 24 Jun 2019 13:02:52 +0200 > Benjamin Baier <program...@netzbasis.de> wrote: > > > Hi, > > > > this is wip for a new sysctl that implements gpu throttling. > > Only implemented for inteldrm right now, and tested on a single amd64 > > laptop. Helps to keep the GPU/CPU cooler and save some energy. > > > > Most of the diff is for sensors to verify if the sysctl works, and will > > be removed once i'm confident enought. > > > > Some notes from my x220 with integrated intel graphics (HD3000): > > - min gpu freq: 650 MHz > > - max gpu freq: 1300 MHz > > Setting hw.gpuperf to anything > 10 (max. 700 MHz) will eventually run > > into thermal throttling (GPU temp 96 deg C). > > Setting hw.gpuperf=0 (650MHz) will run Youtube video and browser games > > together fine, and reduce GPU/CPU temp from 96 deg C to about 80 - 86 deg C. > > > > thoughts? tests? > > > > Greetings Ben > > Thanks, for the feedback. > > Updated diff below. Seems to work without regressions so far on at least > HD3000 (Sandy Bridge), HD4400 (Haswell), HD510 (Skylake), HD405 (Atom x7). > My findings of reduced temps where also replicated. > > === > > This implements a new sysctl hw.gpuperf. > This will throttle down your graphic card for > better thermal and energy management. > Unlike hw.setperf which sets a fixed CPU clock, > hw.gpuperf will limit the max. clock the GPU is > allowed to reach. So it will still downclock while > idle even at hw.gpuperf=100. > > Patch Version 2 > Patch apply directions have changed > Includes man page change > Header cleanup > Patch Version 1 > Throttle down to base freq on haswell & broadwell > Remove sensors, use debug printf > Need: > OpenBSD-current source code > Only implemented for intel graphic (atm.) > To apply: > cd /usr/src && patch < gpuperf.diff > Rebuild and install a new kernel: > KK=`sysctl -n kern.osversion | cut -d# -f1` > cd /usr/src/sys/arch/`machine`/compile/$KK > make obj > make config > make > make install > Rebuild and install a new sysctl: > cp /usr/src/sys/sys/sysctl.h /usr/include/sys/ > cd /usr/src/sbin/sysctl > make obj > make > make install > Test various sysctl hw.gpuperf settings (0, 10, ..., 100) > Send output of: dmesg | grep -e gpuperf -e inteldrm -e cpu0 > and test results/feedback to program...@netzbasis.de > > Wed Jun 26 12:16:25 CEST 2019 > /home/cvsgit/hellfish/src > Index: lib/libc/sys/sysctl.2 > =================================================================== > RCS file: /cvs/src/lib/libc/sys/sysctl.2,v > retrieving revision 1.27 > diff -u -p -r1.27 sysctl.2 > --- lib/libc/sys/sysctl.2 9 May 2019 15:05:47 -0000 1.27 > +++ lib/libc/sys/sysctl.2 26 Jun 2019 10:09:56 -0000 > @@ -282,6 +282,7 @@ privileges may change the value. > .It Dv HW_DISKCOUNT Ta "integer" Ta "no" > .It Dv HW_DISKNAMES Ta "string" Ta "no" > .It Dv HW_DISKSTATS Ta "struct" Ta "no" > +.It Dv HW_GPUPERF Ta "integer" Ta "yes" > .It Dv HW_MACHINE Ta "string" Ta "no" > .It Dv HW_MODEL Ta "string" Ta "no" > .It Dv HW_NCPU Ta "integer" Ta "no" > @@ -324,6 +325,10 @@ A comma-separated list of disk names. > An array of > .Vt struct diskstats > structures containing disk statistics. > +.It Dv HW_GPUPERF Pq Va hw.gpuperf > +Maximum GPU performance > +.Pq percentage . > +Only for supported hardware. > .It Dv HW_MACHINE Pq Va hw.machine > The machine class. > .It Dv HW_MODEL Pq Va hw.model > Index: sys/conf/files > =================================================================== > RCS file: /cvs/src/sys/conf/files,v > retrieving revision 1.671 > diff -u -p -r1.671 files > --- sys/conf/files 4 May 2019 11:34:47 -0000 1.671 > +++ sys/conf/files 25 Jun 2019 20:21:29 -0000 > @@ -710,6 +710,7 @@ file kern/subr_autoconf.c > file kern/subr_disk.c > file kern/subr_evcount.c > file kern/subr_extent.c > +file kern/subr_gpuperf.c inteldrm > file kern/subr_hibernate.c hibernate > file kern/subr_kubsan.c kubsan > file kern/subr_log.c > Index: sys/dev/pci/drm/i915/i915_drv.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_drv.c,v > retrieving revision 1.118 > diff -u -p -r1.118 i915_drv.c > --- sys/dev/pci/drm/i915/i915_drv.c 8 May 2019 15:55:56 -0000 1.118 > +++ sys/dev/pci/drm/i915/i915_drv.c 25 Jun 2019 20:21:29 -0000 > @@ -46,6 +46,10 @@ > #include <drm/drm_atomic_helper.h> > #include <drm/i915_drm.h> > > +#ifdef __OpenBSD__ > +#include <sys/gpuperf.h> > +#endif /* __OpenBSD__ */ > + > #include "i915_drv.h" > #include "i915_trace.h" > #include "i915_pmu.h" > @@ -3668,12 +3672,54 @@ inteldrm_attachhook(struct device *self) > > config_found_sm(self, &aa, wsemuldisplaydevprint, > wsemuldisplaydevsubmatch); > + > +#ifdef __OpenBSD__ > + gpuperf_register(dev_priv->sc_dev.dv_xname, > + inteldrm_set_gpuperf, dev_priv); > +#endif /* __OpenBSD__ */ > + > return; > > fail: > inteldrm_fatal_error = 1; > inteldrm_forcedetach(dev_priv); > } > + > +#ifdef __OpenBSD__ > +#define GPUPERF_DEBUG > +#ifdef GPUPERF_DEBUG > +#define PPRINTF(x...) do { printf(x); } while(0) > +#else > +#define PPRINTF(x...) > +#endif /* GPUPERF_DEBUG */ > +int > +inteldrm_set_gpuperf(int level, void *arg) > +{ > + struct inteldrm_softc *dev_priv = arg; > + struct intel_rps *rps = &dev_priv->gt_pm.rps; > + u_int32_t min = rps->min_freq; > + u_int32_t max = rps->max_freq; > + > + if (max <= min) > + return (-1); > + > + PPRINTF("inteldrm: min %u, max %u, min_s %u, max_s %u, b %u, act %d > MHz\n", > + min, max, rps->min_freq_softlimit, rps->max_freq_softlimit, > + rps->boost_freq, intel_gpu_freq(dev_priv, rps->cur_freq)); > + > + rps->max_freq_softlimit = (u8)((((max - min) * level) / 100) + min); > + rps->boost_freq = rps->max_freq_softlimit; > + > + if (rps->min_freq_softlimit > min) { > + PPRINTF("inteldrm: override min_s (%u > %u). haswell or > broadwell\n", > + rps->min_freq_softlimit, min); > + rps->min_freq_softlimit = min; > + } > + > + /* returning gpu freq, before new performance setting takes effect */ > + return (intel_gpu_freq(dev_priv, rps->cur_freq)); > +} > +#endif /* __OpenBSD__ */ > > int > inteldrm_detach(struct device *self, int flags) > Index: sys/dev/pci/drm/i915/i915_drv.h > =================================================================== > RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_drv.h,v > retrieving revision 1.82 > diff -u -p -r1.82 i915_drv.h > --- sys/dev/pci/drm/i915/i915_drv.h 4 May 2019 11:34:47 -0000 1.82 > +++ sys/dev/pci/drm/i915/i915_drv.h 26 Jun 2019 09:42:42 -0000 > @@ -4014,3 +4014,8 @@ static inline int intel_hws_csb_write_in > } > > #endif > + > +/* gpuperf callback */ > +#ifdef __OpenBSD__ > +int inteldrm_set_gpuperf(int level, void *arg); > +#endif /* __OpenBSD__ */ > Index: sys/kern/kern_sysctl.c > =================================================================== > RCS file: /cvs/src/sys/kern/kern_sysctl.c,v > retrieving revision 1.360 > diff -u -p -r1.360 kern_sysctl.c > --- sys/kern/kern_sysctl.c 16 Jun 2019 00:56:53 -0000 1.360 > +++ sys/kern/kern_sysctl.c 25 Jun 2019 20:21:29 -0000 > @@ -103,6 +103,9 @@ > #include <ddb/db_var.h> > #endif > > +#ifndef SMALL_KERNEL > +#include <sys/gpuperf.h> > +#endif /* !SMALL_KERNEL */ > #ifdef SYSVMSG > #include <sys/msg.h> > #endif > @@ -749,6 +752,8 @@ hw_sysctl(int *name, u_int namelen, void > return (sysctl_hwsetperf(oldp, oldlenp, newp, newlen)); > case HW_PERFPOLICY: > return (sysctl_hwperfpolicy(oldp, oldlenp, newp, newlen)); > + case HW_GPUPERF: > + return (sysctl_hwgpuperf(oldp, oldlenp, newp, newlen)); > #endif /* !SMALL_KERNEL */ > case HW_VENDOR: > if (hw_vendor) > Index: sys/kern/subr_gpuperf.c > =================================================================== > RCS file: sys/kern/subr_gpuperf.c > diff -N sys/kern/subr_gpuperf.c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ sys/kern/subr_gpuperf.c 26 Jun 2019 09:48:03 -0000 > @@ -0,0 +1,91 @@ > +/* $OpenBSD$ */ > + > +/* > + * Copyright (c) 2019 Benjamin Baier <b...@netzbasis.de> > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#include <sys/gpuperf.h> > +#include <sys/param.h> > +#include <sys/systm.h> > +#include <sys/sysctl.h> > + > +#define GPUPERF_DEBUG > +#ifdef GPUPERF_DEBUG > +#define DPRINTF(x...) do { printf(x); } while(0) > +#else > +#define DPRINTF(x...) > +#endif /* GPUPERF_DEBUG */ > + > +struct gpuperf_node { > + char name[16]; /* gpu driver name */ > + int (*callback)(int, void *); /* must understand 0 - 100 as % */ > + void *arg; /* arg passthrough */ > +}; > + > +struct gpuperf_node gpuperf_registered_nodes[GPUPERF_MAX_NODES]; > + > +int gpuperf = 100; > +int gpuperf_gpun = 0; > + > +int > +gpuperf_register(const char *name, int (*callback)(int, void *), void *arg) > +{ > + if (gpuperf_gpun >= GPUPERF_MAX_NODES) > + return (-1); > + > + strlcpy(gpuperf_registered_nodes[gpuperf_gpun].name, name, > + sizeof(gpuperf_registered_nodes[gpuperf_gpun].name)); > + gpuperf_registered_nodes[gpuperf_gpun].callback = callback; > + gpuperf_registered_nodes[gpuperf_gpun].arg = arg; > + > + /* > + * Drivers may take a while to register, even after /etc/sysctl.conf > + * was processed. So immediately call back. > + */ > + (void) callback(gpuperf, arg); > + > + gpuperf_gpun += 1; > + DPRINTF("gpuperf: %s registered (total nodes %d)\n", > + name, gpuperf_gpun); > + > + return (0); > +} > + > +int > +sysctl_hwgpuperf(void *oldp, size_t *oldlenp, void *newp, size_t newlen) > +{ > + int i, err, newperf, dstatus; > + > + newperf = gpuperf; > + err = sysctl_int(oldp, oldlenp, newp, newlen, &newperf); > + if (err) > + return err; > + if (newperf > 100) > + newperf = 100; > + if (newperf < 0) > + newperf = 0; > + gpuperf = newperf; > + > + for (i=0; i < gpuperf_gpun; i++) { > + dstatus = gpuperf_registered_nodes[i].callback(gpuperf, > + gpuperf_registered_nodes[i].arg); > + > + DPRINTF("gpuperf: requesting level %d from %s (dstatus %d)\n", > + gpuperf, gpuperf_registered_nodes[i].name, dstatus); > + > + } > + > + return (0); > +} > Index: sys/sys/gpuperf.h > =================================================================== > RCS file: sys/sys/gpuperf.h > diff -N sys/sys/gpuperf.h > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ sys/sys/gpuperf.h 26 Jun 2019 09:53:51 -0000 > @@ -0,0 +1,29 @@ > +/* $OpenBSD$ */ > + > +/* > + * Copyright (c) 2019 Benjamin Baier <b...@netzbasis.de> > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#ifndef _SYS_GPUPERF_H_ > +#define _SYS_GPUPERF_H_ > + > +#include <sys/types.h> > + > +#define GPUPERF_MAX_NODES 4 > + > +int sysctl_hwgpuperf(void *, size_t *, void *, size_t); > +int gpuperf_register(const char *, int (*)(int, void *), void *); > + > +#endif /* _SYS_GPUPERF_H_ */ > Index: sys/sys/sysctl.h > =================================================================== > RCS file: /cvs/src/sys/sys/sysctl.h,v > retrieving revision 1.189 > diff -u -p -r1.189 sysctl.h > --- sys/sys/sysctl.h 21 Jun 2019 09:39:48 -0000 1.189 > +++ sys/sys/sysctl.h 25 Jun 2019 20:21:29 -0000 > @@ -892,7 +892,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_GPUPERF 26 /* set max GPU performance % */ > +#define HW_MAXID 27 /* number of valid hw ids */ > > #define CTL_HW_NAMES { \ > { 0, 0 }, \ > @@ -921,6 +922,7 @@ struct kinfo_file { > { "perfpolicy", CTLTYPE_STRING }, \ > { "smt", CTLTYPE_INT }, \ > { "ncpuonline", CTLTYPE_INT }, \ > + { "gpuperf", CTLTYPE_INT }, \ > } > > /* > >
-- Chris Humphries <ch...@sogubsys.com> 5223 9548 E1DE DE87 F509 1888 8141 8451 6338 DD29