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", },