On Tue, Sep 17, 2019 at 12:41:11PM -0400, Bryan Steele wrote: > 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 @[email protected] for the providing helpful information and > much needed prodding. > > -Bryan. >
This works on my Ryzen 2700U, thanks! kmsmn0 at pci0 dev 0 function 0 "AMD AMD64 17h/1xh Root Complex" rev 0x00 kmsmn0.temp0 60.88 degC -ml > 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 <[email protected]> > + * > + * 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", > }, >
