[WIP] new sysctl hw.gpuperf

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[WIP] new sysctl hw.gpuperf

Benjamin Baier
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

Mon Jun 24 12:45:07 CEST 2019
/home/cvsgit/hellfish/src/sys
Index: conf/files
===================================================================
RCS file: /cvs/src/sys/conf/files,v
retrieving revision 1.671
diff -u -p -r1.671 files
--- conf/files 4 May 2019 11:34:47 -0000 1.671
+++ conf/files 23 Jun 2019 21:26:46 -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: 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
--- dev/pci/drm/i915/i915_drv.c 8 May 2019 15:55:56 -0000 1.118
+++ dev/pci/drm/i915/i915_drv.c 23 Jun 2019 21:17:19 -0000
@@ -46,6 +46,9 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/i915_drm.h>
 
+#include <sys/gpuperf.h>
+#include <sys/sensors.h>
+
 #include "i915_drv.h"
 #include "i915_trace.h"
 #include "i915_pmu.h"
@@ -3668,11 +3671,91 @@ inteldrm_attachhook(struct device *self)
 
  config_found_sm(self, &aa, wsemuldisplaydevprint,
     wsemuldisplaydevsubmatch);
+
+ strlcpy(dev_priv->sc_sensordev.xname, dev_priv->sc_dev.dv_xname,
+    sizeof(dev_priv->sc_sensordev.xname));
+
+ strlcpy(dev_priv->sc_sensor[0].desc, "gpu clock",
+    sizeof(dev_priv->sc_sensor[0].desc));
+ dev_priv->sc_sensor[0].type = SENSOR_FREQ;
+ sensor_attach(&dev_priv->sc_sensordev, &dev_priv->sc_sensor[0]);
+
+ strlcpy(dev_priv->sc_sensor[1].desc, "mem clock",
+    sizeof(dev_priv->sc_sensor[1].desc));
+ dev_priv->sc_sensor[1].type = SENSOR_FREQ;
+ sensor_attach(&dev_priv->sc_sensordev, &dev_priv->sc_sensor[1]);
+
+ strlcpy(dev_priv->sc_sensor[2].desc, "ring clock",
+    sizeof(dev_priv->sc_sensor[2].desc));
+ dev_priv->sc_sensor[2].type = SENSOR_FREQ;
+ sensor_attach(&dev_priv->sc_sensordev, &dev_priv->sc_sensor[2]);
+
+ strlcpy(dev_priv->sc_sensor[3].desc, "rps level: 0 low, 1 med, 2 high",
+    sizeof(dev_priv->sc_sensor[3].desc));
+ dev_priv->sc_sensor[3].type = SENSOR_INTEGER;
+ sensor_attach(&dev_priv->sc_sensordev, &dev_priv->sc_sensor[3]);
+
+ strlcpy(dev_priv->sc_sensor[4].desc, "min softlimit",
+    sizeof(dev_priv->sc_sensor[4].desc));
+ dev_priv->sc_sensor[4].type = SENSOR_INTEGER;
+ sensor_attach(&dev_priv->sc_sensordev, &dev_priv->sc_sensor[4]);
+
+ strlcpy(dev_priv->sc_sensor[5].desc, "max softlimit",
+    sizeof(dev_priv->sc_sensor[5].desc));
+ dev_priv->sc_sensor[5].type = SENSOR_INTEGER;
+ sensor_attach(&dev_priv->sc_sensordev, &dev_priv->sc_sensor[5]);
+
+ if (sensor_task_register(dev_priv, inteldrm_refresh_sensor, 1) == NULL) {
+ sensor_detach(&dev_priv->sc_sensordev, &dev_priv->sc_sensor[0]);
+ sensor_detach(&dev_priv->sc_sensordev, &dev_priv->sc_sensor[1]);
+ sensor_detach(&dev_priv->sc_sensordev, &dev_priv->sc_sensor[4]);
+ sensor_detach(&dev_priv->sc_sensordev, &dev_priv->sc_sensor[5]);
+ }
+ sensordev_install(&dev_priv->sc_sensordev);
+
+ gpuperf_register(dev_priv->sc_dev.dv_xname,
+    inteldrm_set_gpuperf, dev_priv);
+
  return;
 
 fail:
  inteldrm_fatal_error = 1;
  inteldrm_forcedetach(dev_priv);
+}
+
+void
+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;
+
+ rps->max_freq_softlimit = (u8)((((max - min) * level) / 100) + min);
+ rps->boost_freq = rps->max_freq_softlimit;
+}
+
+void
+inteldrm_refresh_sensor(void *arg)
+{
+ struct inteldrm_softc *dev_priv = arg;
+ struct intel_rps *rps = &dev_priv->gt_pm.rps;
+ int64_t freq0;
+
+ freq0 = intel_gpu_freq(dev_priv, rps->cur_freq);
+ dev_priv->sc_sensor[0].value = freq0 * 1000 * 1000 * 1000 * 1000;
+
+ freq0 = dev_priv->mem_freq;
+ dev_priv->sc_sensor[1].value = freq0 * 1000 * 1000 * 1000 * 1000;
+
+ freq0 = rps->min_freq_softlimit;
+ dev_priv->sc_sensor[4].value = freq0 * 50;
+
+ freq0 = rps->max_freq_softlimit;
+ dev_priv->sc_sensor[5].value = freq0 * 50;
 }
 
 int
Index: 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
--- dev/pci/drm/i915/i915_drv.h 4 May 2019 11:34:47 -0000 1.82
+++ dev/pci/drm/i915/i915_drv.h 23 Jun 2019 21:38:47 -0000
@@ -2274,6 +2274,9 @@ struct inteldrm_softc {
 
  struct i915_pmu pmu;
 
+ struct ksensor sc_sensor[6];
+ struct ksensordev sc_sensordev;
+
  /*
  * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
  * will be rejected. Instead look for a better place.
@@ -4014,3 +4017,6 @@ static inline int intel_hws_csb_write_in
 }
 
 #endif
+
+void inteldrm_set_gpuperf(int level, void *arg);
+void inteldrm_refresh_sensor(void *);
Index: dev/pci/drm/i915/intel_pm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915/intel_pm.c,v
retrieving revision 1.43
diff -u -p -r1.43 intel_pm.c
--- dev/pci/drm/i915/intel_pm.c 14 Apr 2019 10:14:52 -0000 1.43
+++ dev/pci/drm/i915/intel_pm.c 23 Jun 2019 20:02:34 -0000
@@ -6316,6 +6316,8 @@ static void rps_set_power(struct drm_i91
  if (new_power == rps->power.mode)
  return;
 
+ dev_priv->sc_sensor[3].value = new_power;
+
  /* Note the units here are not exactly 1us, but 1280ns. */
  switch (new_power) {
  case LOW_POWER:
@@ -7200,12 +7202,18 @@ static void gen6_update_ring_freq(struct
  * No floor required for ring frequency on SKL.
  */
  ring_freq = gpu_freq;
+ dev_priv->sc_sensor[2].value = ring_freq * 100\
+    * 1000 * 1000 * 1000 * 1000;
  } else if (INTEL_GEN(dev_priv) >= 8) {
  /* max(2 * GT, DDR). NB: GT is 50MHz units */
  ring_freq = max(min_ring_freq, gpu_freq);
+ dev_priv->sc_sensor[2].value = ring_freq * 50\
+    * 1000 * 1000 * 1000 * 1000;
  } else if (IS_HASWELL(dev_priv)) {
  ring_freq = mult_frac(gpu_freq, 5, 4);
  ring_freq = max(min_ring_freq, ring_freq);
+ dev_priv->sc_sensor[2].value = ring_freq * 50\
+    * 1000 * 1000 * 1000 * 1000;
  /* leave ia_freq as the default, chosen by cpufreq */
  } else {
  /* On older processors, there is no separate ring
@@ -7220,6 +7228,7 @@ static void gen6_update_ring_freq(struct
  else
  ia_freq = max_ia_freq - ((diff * scaling_factor) / 2);
  ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100);
+ dev_priv->sc_sensor[2].value = 0;
  }
 
  sandybridge_pcode_write(dev_priv,
Index: 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
--- kern/kern_sysctl.c 16 Jun 2019 00:56:53 -0000 1.360
+++ kern/kern_sysctl.c 24 Jun 2019 09:48:19 -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: kern/subr_gpuperf.c
===================================================================
RCS file: kern/subr_gpuperf.c
diff -N kern/subr_gpuperf.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ kern/subr_gpuperf.c 24 Jun 2019 10:04:35 -0000
@@ -0,0 +1,86 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2019 Benjamin Baier <[hidden email]>
+ *
+ * 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/resourcevar.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 */
+ void (*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, void (*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;
+
+ callback(gpuperf, arg);
+
+ gpuperf_gpun += 1;
+ DPRINTF("gpuperf: %s registered callback (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;
+
+ 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++) {
+ DPRINTF("gpuperf: requesting level %d from %s\n",
+    gpuperf, gpuperf_registered_nodes[i].name);
+
+ gpuperf_registered_nodes[i].callback(gpuperf,
+    gpuperf_registered_nodes[i].arg);
+ }
+
+ return (0);
+}
Index: sys/gpuperf.h
===================================================================
RCS file: sys/gpuperf.h
diff -N sys/gpuperf.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/gpuperf.h 24 Jun 2019 09:05:17 -0000
@@ -0,0 +1,33 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2019 Benjamin Baier <[hidden email]>
+ *
+ * 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_
+
+#ifndef _SIZE_T_DEFINED_
+#define _SIZE_T_DEFINED_
+#include <sys/_types.h>
+typedef __size_t        size_t;
+#endif /* _SIZE_T_DEFINED_ */
+
+#define GPUPERF_MAX_NODES 4
+
+int sysctl_hwgpuperf(void *, size_t *, void *, size_t);
+int gpuperf_register(const char *, void (*)(int, void *), void *);
+
+#endif /* _SYS_GPUPERF_H_ */
Index: sys/sysctl.h
===================================================================
RCS file: /cvs/src/sys/sys/sysctl.h,v
retrieving revision 1.189
diff -u -p -r1.189 sysctl.h
--- sys/sysctl.h 21 Jun 2019 09:39:48 -0000 1.189
+++ sys/sysctl.h 24 Jun 2019 09:02:39 -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 }, \
 }
 
 /*

############################################################
############################################################
Here is an unrelated sysctl(8) diff.
That make sensors print frequency values human readable.

Mon Jun 24 12:45:54 CEST 2019
/home/cvsgit/hellfish/src/sbin/sysctl
Index: sysctl.c
===================================================================
RCS file: /cvs/src/sbin/sysctl/sysctl.c,v
retrieving revision 1.243
diff -u -p -r1.243 sysctl.c
--- sysctl.c 16 Jun 2019 09:30:15 -0000 1.243
+++ sysctl.c 21 Jun 2019 21:15:41 -0000
@@ -2586,6 +2586,7 @@ void
 print_sensor(struct sensor *s)
 {
  const char *name;
+ double freq;
 
  if (s->flags & SENSOR_FUNKNOWN)
  printf("unknown");
@@ -2676,7 +2677,28 @@ print_sensor(struct sensor *s)
  printf("%.2f%%", s->value / 1000.0);
  break;
  case SENSOR_FREQ:
- printf("%.2f Hz", s->value / 1000000.0);
+ /* XXX: this breaks stuff, but the only driver
+ * in the tree that uses SENSOR_FREQ is
+ * usps(4) and I like my MHz numbers
+ * to be human readable
+ */
+ freq = s->value / 1000000.0;
+ if (freq < 10000.00) {
+ printf("%.2f Hz", freq);
+ break;
+ }
+ freq = freq / 1000.00;
+ if (freq < 10000.00) {
+ printf("%.2f kHz", freq);
+ break;
+ }
+ freq = freq / 1000.00;
+ if (freq < 10000.00) {
+ printf("%.2f MHz", freq);
+ break;
+ }
+ freq = freq / 1000.00;
+ printf("%.2f GHz", freq);
  break;
  case SENSOR_ANGLE:
  printf("%3.4f degrees", s->value / 1000000.0);

############################################################
############################################################
OpenBSD 6.5-current (GENERIC.MP) #25: Mon Jun 24 12:04:39 CEST 2019
    [hidden email]:/home/cvsgit/hellfish/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 8451125248 (8059MB)
avail mem = 8184868864 (7805MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.6 @ 0xdae9c000 (64 entries)
bios0: vendor LENOVO version "8DET69WW (1.39 )" date 07/18/2013
bios0: LENOVO 4287CTO
acpi0 at bios0: ACPI 4.0
acpi0: sleep states S0 S3 S4 S5
acpi0: tables DSDT FACP SLIC SSDT SSDT SSDT HPET APIC MCFG ECDT ASF! TCPA SSDT SSDT DMAR UEFI UEFI UEFI
acpi0: wakeup devices LID_(S3) SLPB(S3) IGBE(S4) EXP4(S4) EXP7(S4) EHC1(S3) EHC2(S3) HDEF(S4)
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpihpet0 at acpi0: 14318179 Hz
acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz, 2492.22 MHz, 06-2a-07
cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,NXE,RDTSCP,LONG,LAHF,PERF,ITSC,MD_CLEAR,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,MELTDOWN
cpu0: 256KB 64b/line 8-way L2 cache
cpu0: smt 0, core 0, package 0
mtrr: Pentium Pro MTRR support, 10 var ranges, 88 fixed ranges
cpu0: apic clock running at 99MHz
cpu0: mwait min=64, max=64, C-substates=0.2.1.1.2, IBE
cpu1 at mainbus0: apid 1 (application processor)
cpu1: Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz, 2491.91 MHz, 06-2a-07
cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,NXE,RDTSCP,LONG,LAHF,PERF,ITSC,MD_CLEAR,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,MELTDOWN
cpu1: 256KB 64b/line 8-way L2 cache
cpu1: smt 1, core 0, package 0
cpu2 at mainbus0: apid 2 (application processor)
cpu2: Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz, 2491.91 MHz, 06-2a-07
cpu2: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,NXE,RDTSCP,LONG,LAHF,PERF,ITSC,MD_CLEAR,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,MELTDOWN
cpu2: 256KB 64b/line 8-way L2 cache
cpu2: smt 0, core 1, package 0
cpu3 at mainbus0: apid 3 (application processor)
cpu3: Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz, 2491.91 MHz, 06-2a-07
cpu3: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,NXE,RDTSCP,LONG,LAHF,PERF,ITSC,MD_CLEAR,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,MELTDOWN
cpu3: 256KB 64b/line 8-way L2 cache
cpu3: smt 1, core 1, package 0
ioapic0 at mainbus0: apid 2 pa 0xfec00000, version 20, 24 pins
acpimcfg0 at acpi0
acpimcfg0: addr 0xf8000000, bus 0-63
acpiec0 at acpi0
acpiprt0 at acpi0: bus 0 (PCI0)
acpiprt1 at acpi0: bus -1 (PEG_)
acpiprt2 at acpi0: bus 2 (EXP1)
acpiprt3 at acpi0: bus 3 (EXP2)
acpiprt4 at acpi0: bus 5 (EXP4)
acpiprt5 at acpi0: bus 13 (EXP5)
acpiprt6 at acpi0: bus -1 (EXP7)
acpicpu0 at acpi0: C3(350@104 io@0x415), C1(1000@1 halt), PSS
acpicpu1 at acpi0: C3(350@104 io@0x415), C1(1000@1 halt), PSS
acpicpu2 at acpi0: C3(350@104 io@0x415), C1(1000@1 halt), PSS
acpicpu3 at acpi0: C3(350@104 io@0x415), C1(1000@1 halt), PSS
acpipwrres0 at acpi0: PUBS, resource for EHC1, EHC2
acpitz0 at acpi0: critical temperature is 99 degC
acpibtn0 at acpi0: LID_
acpibtn1 at acpi0: SLPB
acpipci0 at acpi0 PCI0: 0x00000000 0x00000011 0x00000001
acpicmos0 at acpi0
acpibat0 at acpi0: BAT0 model "42T4861" serial 12675 type LION oem "SANYO"
acpiac0 at acpi0: AC unit online
acpithinkpad0 at acpi0
"IBM0079" at acpi0 not configured
"PNP0C14" at acpi0 not configured
"PNP0C14" at acpi0 not configured
acpidock0 at acpi0: GDCK docked (15)
acpivideo0 at acpi0: VID_
acpivout at acpivideo0 not configured
acpivideo1 at acpi0: VID_
cpu0: using VERW MDS workaround (except on vmm entry)
cpu0: Enhanced SpeedStep 2492 MHz: speeds: 2501, 2500, 2200, 2000, 1800, 1600, 1400, 1200, 1000, 800 MHz
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "Intel Core 2G Host" rev 0x09
inteldrm0 at pci0 dev 2 function 0 "Intel HD Graphics 3000" rev 0x09
drm0 at inteldrm0
inteldrm0: msi
"Intel 6 Series MEI" rev 0x04 at pci0 dev 22 function 0 not configured
em0 at pci0 dev 25 function 0 "Intel 82579LM" rev 0x04: msi, address f0:de:f1:cd:a7:0f
ehci0 at pci0 dev 26 function 0 "Intel 6 Series USB" rev 0x04: apic 2 int 16
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 configuration 1 interface 0 "Intel EHCI root hub" rev 2.00/1.00 addr 1
azalia0 at pci0 dev 27 function 0 "Intel 6 Series HD Audio" rev 0x04: msi
azalia0: codecs: Conexant CX20590, Intel/0x2805, using Conexant CX20590
audio0 at azalia0
ppb0 at pci0 dev 28 function 0 "Intel 6 Series PCIE" rev 0xb4: msi
pci1 at ppb0 bus 2
ppb1 at pci0 dev 28 function 1 "Intel 6 Series PCIE" rev 0xb4: msi
pci2 at ppb1 bus 3
iwn0 at pci2 dev 0 function 0 "Intel Centrino Advanced-N 6205" rev 0x34: msi, MIMO 2T2R, MoW, address 10:0b:a9:9e:65:34
ppb2 at pci0 dev 28 function 3 "Intel 6 Series PCIE" rev 0xb4: msi
pci3 at ppb2 bus 5
ppb3 at pci0 dev 28 function 4 "Intel 6 Series PCIE" rev 0xb4: msi
pci4 at ppb3 bus 13
sdhc0 at pci4 dev 0 function 0 "Ricoh 5U822 SD/MMC" rev 0x07: apic 2 int 16
sdhc0: SDHC 3.0, 50 MHz base clock
sdmmc0 at sdhc0: 4-bit, sd high-speed, mmc high-speed, dma
ehci1 at pci0 dev 29 function 0 "Intel 6 Series USB" rev 0x04: apic 2 int 23
usb1 at ehci1: USB revision 2.0
uhub1 at usb1 configuration 1 interface 0 "Intel EHCI root hub" rev 2.00/1.00 addr 1
pcib0 at pci0 dev 31 function 0 "Intel QM67 LPC" rev 0x04
ahci0 at pci0 dev 31 function 2 "Intel 6 Series AHCI" rev 0x04: msi, AHCI 1.3
ahci0: port 0: 6.0Gb/s
ahci0: port 1: 1.5Gb/s
ahci0: port 2: 3.0Gb/s
scsibus1 at ahci0: 32 targets
sd0 at scsibus1 targ 0 lun 0: <ATA, SanDisk SD6SB1M1, X230> SCSI3 0/direct fixed naa.5001b449c700768f
sd0: 122104MB, 512 bytes/sector, 250069680 sectors, thin
cd0 at scsibus1 targ 1 lun 0: <Optiarc, DVD RW AD-7930H, 1.D1> ATAPI 5/cdrom removable
sd1 at scsibus1 targ 2 lun 0: <ATA, TOSHIBA THNSNH25, HTGA> SCSI3 0/direct fixed naa.500080db000064dc
sd1: 244198MB, 512 bytes/sector, 500118192 sectors, thin
ichiic0 at pci0 dev 31 function 3 "Intel 6 Series SMBus" rev 0x04: apic 2 int 18
iic0 at ichiic0
spdmem0 at iic0 addr 0x50: 4GB DDR3 SDRAM PC3-10600 SO-DIMM
spdmem1 at iic0 addr 0x51: 4GB DDR3 SDRAM PC3-10600 SO-DIMM
isa0 at pcib0
isadma0 at isa0
pckbc0 at isa0 port 0x60/5 irq 1 irq 12
pckbd0 at pckbc0 (kbd slot)
wskbd0 at pckbd0: console keyboard
pms0 at pckbc0 (aux slot)
wsmouse0 at pms0 mux 0
wsmouse1 at pms0 mux 0
pms0: Synaptics clickpad, firmware 8.0, 0x1e2b1 0x940300
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
aps0 at isa0 port 0x1600/31
vmm0 at mainbus0: VMX/EPT
uhub2 at uhub0 port 1 configuration 1 interface 0 "Intel Rate Matching Hub" rev 2.00/0.00 addr 2
uhub3 at uhub2 port 1 configuration 1 interface 0 "Standard Microsystems product 0x2514" rev 2.00/0.00 addr 3
uhidev0 at uhub3 port 2 configuration 1 interface 0 "TypeMatrix.com USB Keyboard" rev 1.10/1.50 addr 4
uhidev0: iclass 3/1
ukbd0 at uhidev0: 8 variable keys, 6 key codes
wskbd1 at ukbd0 mux 1
uhidev1 at uhub3 port 2 configuration 1 interface 1 "TypeMatrix.com USB Keyboard" rev 1.10/1.50 addr 4
uhidev1: iclass 3/1, 3 report ids
uhid0 at uhidev1 reportid 1: input=1, output=0, feature=0
uhid1 at uhidev1 reportid 2: input=2, output=0, feature=0
uhid2 at uhidev1 reportid 3: input=2, output=1, feature=0
uhidev2 at uhub3 port 4 configuration 1 interface 0 "SteelSeries Kinzu V2 Gaming Mouse" rev 1.10/0.96 addr 5
uhidev2: iclass 3/0
uhid3 at uhidev2: input=32, output=32, feature=255
uhidev3 at uhub3 port 4 configuration 1 interface 1 "SteelSeries Kinzu V2 Gaming Mouse" rev 1.10/0.96 addr 5
uhidev3: iclass 3/1
ums0 at uhidev3: 8 buttons, Z dir
wsmouse2 at ums0 mux 0
ugen0 at uhub2 port 4 "Broadcom Corp Broadcom Bluetooth Device" rev 2.00/7.48 addr 6
uvideo0 at uhub2 port 6 configuration 1 interface 0 "Chicony Electronics Co., Ltd. Integrated Camera" rev 2.00/8.54 addr 7
video0 at uvideo0
uhub4 at uhub1 port 1 configuration 1 interface 0 "Intel Rate Matching Hub" rev 2.00/0.00 addr 2
vscsi0 at root
scsibus2 at vscsi0: 256 targets
softraid0 at root
scsibus3 at softraid0: 256 targets
sd2 at scsibus3 targ 1 lun 0: <OPENBSD, SR RAID 0, 006> SCSI2 0/direct fixed
sd2: 223732MB, 512 bytes/sector, 458204672 sectors
root on sd1a (cb2b25d2bc04572e.a) swap on sd1b dump on sd1b
inteldrm0: 1366x768, 32bpp
wsdisplay0 at inteldrm0 mux 1: console (std, vt100 emulation), using wskbd0
wskbd1: connecting to wsdisplay0
wsdisplay0: screen 1-5 added (std, vt100 emulation)
wskbd1: disconnecting from wsdisplay0
wskbd1 detached
ukbd0 detached
uhidev0 detached
uhid0 detached
uhid1 detached
uhid2 detached
uhidev1 detached
uhidev0 at uhub3 port 2 configuration 1 interface 0 "TypeMatrix.com USB Keyboard" rev 1.10/1.50 addr 4
uhidev0: iclass 3/1
ukbd0 at uhidev0: 8 variable keys, 6 key codes
wskbd1 at ukbd0: console keyboard, using wsdisplay0
uhidev1 at uhub3 port 2 configuration 1 interface 1 "TypeMatrix.com USB Keyboard" rev 1.10/1.50 addr 4
uhidev1: iclass 3/1, 3 report ids
uhid0 at uhidev1 reportid 1: input=1, output=0, feature=0
uhid1 at uhidev1 reportid 2: input=2, output=0, feature=0
uhid2 at uhidev1 reportid 3: input=2, output=1, feature=0

Reply | Threaded
Open this post in threaded view
|

Re: [WIP] new sysctl hw.gpuperf

Benjamin Baier
On Mon, 24 Jun 2019 13:02:52 +0200
Benjamin Baier <[hidden email]> 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 [hidden email]

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 <[hidden email]>
+ *
+ * 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 <[hidden email]>
+ *
+ * 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 }, \
 }
 
 /*


Reply | Threaded
Open this post in threaded view
|

Re: [WIP] new sysctl hw.gpuperf

Chris Humphries-2
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 <[hidden email]> 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 [hidden email]
>
> 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 <[hidden email]>
> + *
> + * 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 <[hidden email]>
> + *
> + * 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 <[hidden email]>
5223 9548 E1DE DE87 F509  1888 8141 8451 6338 DD29