On Sun, Apr 24, 2022 at 07:06:19PM +0200, Claudio Jeker wrote: > On Ryzen CPUs each CCD has a temp sensor. If the CPU has CCDs (which > excludes Zen APU CPUs) this should show additional temp info. This is > based on info from the Linux k10temp driver. > > Additionally use the MSRs defined in "Open-Source Register Reference For > AMD Family 17h Processors" to measure the CPU core frequency. > That should be the actuall speed of the CPU core during the measuring > interval. > > On my T14g2 the output is now for example: > ksmn0.temp0 63.88 degC Tctl > ksmn0.frequency0 3553141515.00 Hz CPU0 > ksmn0.frequency1 3549080315.00 Hz CPU2 > ksmn0.frequency2 3552369937.00 Hz CPU4 > ksmn0.frequency3 3546055048.00 Hz CPU6 > ksmn0.frequency4 3546854449.00 Hz CPU8 > ksmn0.frequency5 3543869698.00 Hz CPU10 > ksmn0.frequency6 3542551127.00 Hz CPU12 > ksmn0.frequency7 4441623647.00 Hz CPU14 > > It is intresting to watch turbo kick in and how temp causes the CPU to > throttle. > > I only tested this on systems with APUs so I could not thest the Tccd temp > reporting.
With the frequence sensor moved to cpu(4) this just adds the Tccd additional temparature sensors. It does not fix the duplication of the ksmn(4) sensors. That needs to be fixed by no attaching on the duplicate root complexes. How that is done I still need to figure out. -- :wq Claudio Index: ksmn.c =================================================================== RCS file: /cvs/src/sys/dev/pci/ksmn.c,v retrieving revision 1.6 diff -u -p -r1.6 ksmn.c --- ksmn.c 11 Mar 2022 18:00:50 -0000 1.6 +++ ksmn.c 25 Apr 2022 15:19:21 -0000 @@ -42,6 +42,7 @@ * [31:21] Current reported temperature. */ #define SMU_17H_THM 0x59800 +#define SMU_17H_CCD_THM(o, x) (SMU_17H_THM + (o) + ((x) * 4)) #define GET_CURTMP(r) (((r) >> 21) & 0x7ff) /* @@ -50,6 +51,8 @@ */ #define CURTMP_17H_RANGE_SEL (1 << 19) #define CURTMP_17H_RANGE_ADJUST 490 +#define CURTMP_CCD_VALID (1 << 11) +#define CURTMP_CCD_MASK 0x7ff /* * Undocumented tCTL offsets gleamed from Linux k10temp driver. @@ -75,13 +78,18 @@ struct ksmn_softc { pcitag_t sc_pcitag; int sc_tctl_offset; + unsigned int sc_ccd_valid; /* available Tccds */ + unsigned int sc_ccd_offset; - struct ksensor sc_sensor; struct ksensordev sc_sensordev; + struct ksensor sc_sensor; /* Tctl */ + struct ksensor sc_ccd_sensor[12]; /* Tccd */ }; int ksmn_match(struct device *, void *, void *); void ksmn_attach(struct device *, struct device *, void *); +uint32_t ksmn_read_reg(struct ksmn_softc *, uint32_t); +void ksmn_ccd_attach(struct ksmn_softc *, int); void ksmn_refresh(void *); const struct cfattach ksmn_ca = { @@ -113,7 +121,9 @@ ksmn_attach(struct device *parent, struc struct ksmn_softc *sc = (struct ksmn_softc *)self; struct pci_attach_args *pa = aux; struct curtmp_offset *p; - extern char cpu_model[]; + struct cpu_info *ci = curcpu(); + extern char cpu_model[]; + sc->sc_pc = pa->pa_pc; sc->sc_pcitag = pa->pa_tag; @@ -122,6 +132,7 @@ ksmn_attach(struct device *parent, struc sizeof(sc->sc_sensordev.xname)); sc->sc_sensor.type = SENSOR_TEMP; + snprintf(sc->sc_sensor.desc, sizeof(sc->sc_sensor.desc), "Tctl"); sensor_attach(&sc->sc_sensordev, &sc->sc_sensor); /* @@ -136,6 +147,38 @@ ksmn_attach(struct device *parent, struc sc->sc_tctl_offset = p->tctl_offset; } + sc->sc_ccd_offset = 0x154; + + if (ci->ci_family == 0x17 || ci->ci_family == 0x18) { + switch (ci->ci_model) { + case 0x1: /* Zen */ + case 0x8: /* Zen+ */ + case 0x11: /* Zen APU */ + case 0x18: /* Zen+ APU */ + ksmn_ccd_attach(sc, 4); + break; + case 0x31: /* Zen2 Threadripper */ + case 0x60: /* Renoir */ + case 0x68: /* Lucienne */ + case 0x71: /* Zen2 */ + ksmn_ccd_attach(sc, 8); + break; + } + } else if (ci->ci_family == 0x19) { + uint32_t m = ci->ci_model; + + if ((m >= 0x40 && m <= 0x4f) || + (m >= 0x10 && m <= 0x1f) || + (m >= 0xa0 && m <= 0xaf)) + sc->sc_ccd_offset = 0x300; + + if ((m >= 0x10 && m <= 0x1f) || + (m >= 0xa0 && m <= 0xaf)) + ksmn_ccd_attach(sc, 12); + else + ksmn_ccd_attach(sc, 8); + } + if (sensor_task_register(sc, ksmn_refresh, 5) == NULL) { printf(": unable to register update task\n"); return; @@ -146,18 +189,49 @@ ksmn_attach(struct device *parent, struc printf("\n"); } +uint32_t +ksmn_read_reg(struct ksmn_softc *sc, uint32_t addr) +{ + uint32_t reg; + int s; + + s = splhigh(); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, SMN_17H_ADDR_R, addr); + reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, SMN_17H_DATA_R); + splx(s); + return reg; +} + +void +ksmn_ccd_attach(struct ksmn_softc *sc, int nccd) +{ + struct ksensor *s; + uint32_t reg; + int i; + + KASSERT(nccd > 0 && nccd < nitems(sc->sc_ccd_sensor)); + + for (i = 0; i < nccd; i++) { + reg = ksmn_read_reg(sc, SMU_17H_CCD_THM(sc->sc_ccd_offset, i)); + if (reg & CURTMP_CCD_VALID) { + sc->sc_ccd_valid |= (1 << i); + s = &sc->sc_ccd_sensor[i]; + s->type = SENSOR_TEMP; + snprintf(s->desc, sizeof(s->desc), "Tccd%d", i); + sensor_attach(&sc->sc_sensordev, s); + } + } +} + void ksmn_refresh(void *arg) { struct ksmn_softc *sc = arg; struct ksensor *s = &sc->sc_sensor; pcireg_t reg; - int raw, offset = 0; - - 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); + int i, raw, offset = 0; + reg = ksmn_read_reg(sc, SMU_17H_THM); raw = GET_CURTMP(reg); if ((reg & CURTMP_17H_RANGE_SEL) != 0) offset -= CURTMP_17H_RANGE_ADJUST; @@ -166,5 +240,16 @@ ksmn_refresh(void *arg) offset *= 100000; /* convert raw (in steps of 0.125C) to uC, add offset, uC to uK. */ - s->value = ((raw * 125000) + offset) + 273150000; + s->value = raw * 125000 + offset + 273150000; + + offset = CURTMP_17H_RANGE_ADJUST * 100000; + for (i = 0; i < nitems(sc->sc_ccd_sensor); i++) { + if (sc->sc_ccd_valid & (1 << i)) { + s = &sc->sc_ccd_sensor[i]; + reg = ksmn_read_reg(sc, + SMU_17H_CCD_THM(sc->sc_ccd_offset, i)); + s->value = (reg & CURTMP_CCD_MASK) * 125000 - offset + + 273150000; + } + } }