Unlike with previous generations of AMD processors, the on-die
temperature sensor is only available from reading from the SMU
co-processor over an internal network (SMN), this includes all
Ryzen CPUs and some later Family 15h models (not supported here).

This adds a new driver based on km(4) and info gleamed from Linux
FreeBSD.

High-TDP Zen/Zen+ parts have undocumented offsets from the control temp
and need to be adjusted, low-TDP (mobile) and Zen2 have no offsets.

I've tested this on a Ryzen 2700X desktop and a Ryzen 5 2500U (mobile)
laptop (no offset). I would appreciate feedback on other models, and
confirmation about Zen2.

Thanks to @nte@bsd.network for the providing helpful information and
much needed prodding.

-Bryan.

Index: arch/amd64/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v
retrieving revision 1.478
diff -u -p -u -r1.478 GENERIC
--- sys/arch/amd64/conf/GENERIC 7 Sep 2019 13:46:19 -0000       1.478
+++ sys/arch/amd64/conf/GENERIC 17 Sep 2019 16:24:03 -0000
@@ -103,6 +103,7 @@ amdpcib* at pci?            # AMD 8111 LPC bridge
 tcpcib*        at pci?                 # Intel Atom E600 LPC bridge
 kate*  at pci?                 # AMD K8 temperature sensor
 km*    at pci?                 # AMD K10 temperature sensor
+kmsmn* at pci?                 # AMD F17 temperature sensor
 amas*  at pci? disable         # AMD memory configuration
 pchtemp* at pci?               # Intel C610 termperature sensor
 ccp*   at pci?                 # AMD Cryptographic Co-processor
Index: dev/pci/files.pci
===================================================================
RCS file: /cvs/src/sys/dev/pci/files.pci,v
retrieving revision 1.338
diff -u -p -u -r1.338 files.pci
--- sys/dev/pci/files.pci       5 Aug 2019 08:33:38 -0000       1.338
+++ sys/dev/pci/files.pci       17 Sep 2019 16:24:03 -0000
@@ -774,6 +774,11 @@ device     km
 attach km at pci
 file   dev/pci/km.c                    km
 
+# AMD Family 15h/17h Temperature sensor over SMN
+device kmsmn
+attach kmsmn at pci
+file   dev/pci/kmsmn.c                 kmsmn
+
 # Intel SOC GCU
 device gcu
 attach gcu at pci
Index: dev/pci/kmsmn.c
===================================================================
RCS file: dev/pci/kmsmn.c
diff -N dev/pci/kmsmn.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/dev/pci/kmsmn.c 17 Sep 2019 16:24:03 -0000
@@ -0,0 +1,170 @@
+/*     $OpenBSD$       */
+
+/*
+ * Copyright (c) 2019 Bryan Steele <bry...@openbsd.org>
+ *
+ * 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/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/sensors.h>
+
+#include <machine/bus.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+/*
+ * AMD temperature sensors on Family 17h (and some 15h) must be
+ * read from the System Management Unit (SMU) co-processor over
+ * the System Management Network (SMN).
+ */
+
+#define SMN_17H_ADDR_R 0x60
+#define SMN_17H_DATA_R 0x64
+
+/*
+  * AMD Family 17h SMU Thermal Registers (THM)
+  *
+  * 4.2.1, OSRR (Open-Source Register Reference) Guide for Family 17h
+  *     [31:21]  Current reported temperature.
+  */
+#define SMU_17H_THM            0x59800
+#define KM_GET_CURTMP(r)       (((r) >> 21) & 0x7ff)
+
+/*
+ * Bit 19 set: "Report on -49C to 206C scale range."
+ *      clear: "Report on 0C to 225C (255C?) scale range."
+ */
+#define CURTMP_17H_RANGE_SEL   (1 << 19)
+#define CURTMP_17H_RANGE_ADJUST        490
+
+/*
+ * Undocumented tCTL offsets gleamed from Linux k10temp driver.
+ */
+struct curtmp_offset {
+       const char *const cpu_model; /* partial match */
+       int tctl_offset;
+} cpu_model_offsets[] = {
+       { "AMD Ryzen 5 1600X", 200 },
+       { "AMD Ryzen 7 1700X", 200 },
+       { "AMD Ryzen 7 1800X", 200 },
+       { "AMD Ryzen 7 2700X", 100 },
+       { "AMD Ryzen Threadripper 19", 270 }, /* many models */
+       { "AMD Ryzen Threadripper 29", 270 }, /* many models */
+       { NULL, 0 },
+       /* ... */
+};
+
+struct kmsmn_softc {
+       struct device           sc_dev;
+
+       pci_chipset_tag_t       sc_pc;
+       pcitag_t                sc_pcitag;
+
+       int                     sc_tctl_offset;
+       struct mutex            sc_smnlock;
+
+       struct ksensor          sc_sensor;
+       struct ksensordev       sc_sensordev;
+};
+
+int    kmsmn_match(struct device *, void *, void *);
+void   kmsmn_attach(struct device *, struct device *, void *);
+void   kmsmn_refresh(void *);
+
+struct cfattach kmsmn_ca = {
+       sizeof(struct kmsmn_softc), kmsmn_match, kmsmn_attach
+};
+
+struct cfdriver kmsmn_cd = {
+       NULL, "kmsmn", DV_DULL
+};
+
+static const struct pci_matchid kmsmn_devices[] = {
+       { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_17_RC },
+       { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_17_1X_RC },
+       { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_17_3X_RC }
+};
+
+int
+kmsmn_match(struct device *parent, void *match, void *aux)
+{
+       /* successful match supersedes pchb(4) */
+       return pci_matchbyid((struct pci_attach_args *)aux, kmsmn_devices,
+           sizeof(kmsmn_devices) / sizeof(kmsmn_devices[0])) * 2;
+}
+
+void
+kmsmn_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct kmsmn_softc      *sc = (struct kmsmn_softc *)self;
+       struct pci_attach_args  *pa = aux;
+       struct curtmp_offset    *p;
+       extern char             cpu_model[];
+
+       sc->sc_pc = pa->pa_pc;
+       sc->sc_pcitag = pa->pa_tag;
+
+       strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
+           sizeof(sc->sc_sensordev.xname));
+
+       sc->sc_sensor.type = SENSOR_TEMP;
+       sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
+
+       /*
+        * Zen/Zen+ CPUs are offset if TDP > 65, otherwise 0.
+        * Zen 2 models appear to have no tCTL offset, so always 0.
+        *
+        * XXX: Does any public documentation exist for this?
+        */
+       for (p = cpu_model_offsets; p->cpu_model != NULL; p++) {
+               if (!strncmp(cpu_model, p->cpu_model, strlen(p->cpu_model)))
+                       sc->sc_tctl_offset = p->tctl_offset;
+       }
+
+       /* For accessing the SMU */
+       mtx_init(&sc->sc_smnlock, IPL_NONE);
+       if (sensor_task_register(sc, kmsmn_refresh, 5) == NULL) {
+               printf(": unable to register update task\n");
+               return;
+       }
+
+       sensordev_install(&sc->sc_sensordev);
+
+       printf("\n");
+}
+
+void
+kmsmn_refresh(void *arg)
+{
+       struct kmsmn_softc      *sc = arg;
+       struct ksensor  *s = &sc->sc_sensor;
+       pcireg_t        reg;
+       int             c;
+
+       mtx_enter(&sc->sc_smnlock);
+       pci_conf_write(sc->sc_pc, sc->sc_pcitag, SMN_17H_ADDR_R,
+           SMU_17H_THM);
+       reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, SMN_17H_DATA_R);
+       mtx_leave(&sc->sc_smnlock);
+
+       c = KM_GET_CURTMP(reg) * 5 / 4; /* 1.25 */
+       if ((reg & CURTMP_17H_RANGE_SEL) != 0)
+               c -= CURTMP_17H_RANGE_ADJUST;
+       if (c > sc->sc_tctl_offset)
+               c -= sc->sc_tctl_offset;
+       s->value = c * 125000 + 273150000;
+}
Index: dev/pci/pcidevs
===================================================================
RCS file: /cvs/src/sys/dev/pci/pcidevs,v
retrieving revision 1.1895
diff -u -p -u -r1.1895 pcidevs
--- sys/dev/pci/pcidevs 23 Aug 2019 01:18:08 -0000      1.1895
+++ sys/dev/pci/pcidevs 17 Sep 2019 16:24:03 -0000
@@ -753,6 +753,7 @@ product AMD AMD64_17_DF_8   0x1467  AMD64 1
 product AMD AMD64_17_CCP_2     0x1468  AMD64 17h Crypto
 product AMD AMD64_17_PCIE_4    0x1470  AMD64 17h PCIE
 product AMD AMD64_17_PCIE_5    0x1471  AMD64 17h PCIE
+product AMD AMD64_17_3X_RC     0x1480  AMD64 17h/3xh Root Complex
 product AMD AMD64_14_HB                0x1510  AMD64 14h Host
 product AMD AMD64_14_PCIE_1    0x1512  AMD64 14h PCIE
 product AMD AMD64_14_PCIE_2    0x1513  AMD64 14h PCIE
Index: dev/pci/pcidevs.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/pcidevs.h,v
retrieving revision 1.1888
diff -u -p -u -r1.1888 pcidevs.h
--- sys/dev/pci/pcidevs.h       23 Aug 2019 01:19:24 -0000      1.1888
+++ sys/dev/pci/pcidevs.h       17 Sep 2019 16:24:04 -0000
@@ -758,6 +758,7 @@
 #define        PCI_PRODUCT_AMD_AMD64_17_CCP_2  0x1468          /* AMD64 17h 
Crypto */
 #define        PCI_PRODUCT_AMD_AMD64_17_PCIE_4 0x1470          /* AMD64 17h 
PCIE */
 #define        PCI_PRODUCT_AMD_AMD64_17_PCIE_5 0x1471          /* AMD64 17h 
PCIE */
+#define        PCI_PRODUCT_AMD_AMD64_17_3X_RC  0x1480          /* AMD64 
17h/3xh Root Complex */
 #define        PCI_PRODUCT_AMD_AMD64_14_HB     0x1510          /* AMD64 14h 
Host */
 #define        PCI_PRODUCT_AMD_AMD64_14_PCIE_1 0x1512          /* AMD64 14h 
PCIE */
 #define        PCI_PRODUCT_AMD_AMD64_14_PCIE_2 0x1513          /* AMD64 14h 
PCIE */
Index: dev/pci/pcidevs_data.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/pcidevs_data.h,v
retrieving revision 1.1883
diff -u -p -u -r1.1883 pcidevs_data.h
--- sys/dev/pci/pcidevs_data.h  23 Aug 2019 01:19:24 -0000      1.1883
+++ sys/dev/pci/pcidevs_data.h  17 Sep 2019 16:24:04 -0000
@@ -1356,6 +1356,10 @@ static const struct pci_known_product pc
            "AMD64 17h PCIE",
        },
        {
+           PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_17_3X_RC,
+           "AMD64 17h/3xh Root Complex",
+       },
+       {
            PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_14_HB,
            "AMD64 14h Host",
        },

Reply via email to