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

Reply via email to