diff --git a/sys/arch/x86/x86/viac7temp.c b/sys/arch/x86/x86/viac7temp.c index 333a5e0c40b..865788e0605 100644 --- a/sys/arch/x86/x86/viac7temp.c +++ b/sys/arch/x86/x86/viac7temp.c @@ -42,11 +42,15 @@ __KERNEL_RCSID(0, "$NetBSD: viac7temp.c,v 1.10 2024/04/13 09:12:09 andvar Exp $" #include #include +#define MSR_TEMP_NANO 0x1423 /* VIA Nano and Zhaoxin CPUs */ +#define MSR_TEMP_C7 0x1169 /* VIA C7 CPUs */ + struct viac7temp_softc { device_t sc_dev; struct cpu_info *sc_ci; struct sysmon_envsys *sc_sme; envsys_data_t sc_sensor; + uint32_t sc_temp_msr; }; static int viac7temp_match(device_t, cfdata_t, void *); @@ -54,6 +58,7 @@ static void viac7temp_attach(device_t, device_t, void *); static int viac7temp_detach(device_t, int); static void viac7temp_refresh(struct sysmon_envsys *, envsys_data_t *); static void viac7temp_refresh_xcall(void *, void *); +static uint32_t viac7temp_msr_register(struct cpu_info *ci); CFATTACH_DECL_NEW(viac7temp, sizeof(struct viac7temp_softc), viac7temp_match, viac7temp_attach, viac7temp_detach, NULL); @@ -63,8 +68,8 @@ viac7temp_match(device_t parent, cfdata_t cf, void *aux) { struct cpufeature_attach_args *cfaa = aux; struct cpu_info *ci = cfaa->ci; - uint32_t family, model; - uint32_t descs[4]; + uint32_t temp_msr; + uint64_t val; if (strcmp(cfaa->name, "temperature") != 0) return 0; @@ -72,18 +77,12 @@ viac7temp_match(device_t parent, cfdata_t cf, void *aux) if (cpu_vendor != CPUVENDOR_IDT) return 0; - model = CPUID_TO_MODEL(ci->ci_signature); - family = CPUID_TO_FAMILY(ci->ci_signature); + temp_msr = viac7temp_msr_register(ci); - if (family != 0x06 || model < 0x09) + if (!temp_msr || rdmsr_safe(temp_msr, &val) == EFAULT) return 0; - x86_cpuid(0xc0000000, descs); - - if (descs[0] >= 0xc0000002) - return 1; - - return 0; + return 1; } static void @@ -100,6 +99,8 @@ viac7temp_attach(device_t parent, device_t self, void *aux) sc->sc_sensor.flags = ENVSYS_FMONLIMITS|ENVSYS_FHAS_ENTROPY; sc->sc_sensor.state = ENVSYS_SINVALID; + sc->sc_temp_msr = viac7temp_msr_register(ci); + (void)strlcpy(sc->sc_sensor.desc, "temperature", sizeof(sc->sc_sensor.desc)); @@ -116,7 +117,7 @@ viac7temp_attach(device_t parent, device_t self, void *aux) goto fail; aprint_naive("\n"); - aprint_normal(": VIA C7 temperature sensor\n"); + aprint_normal(": VIA C7/Nano temperature sensor\n"); (void)pmf_device_register(self, NULL, NULL); @@ -153,17 +154,44 @@ viac7temp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) static void viac7temp_refresh_xcall(void *arg0, void *arg1) { + struct viac7temp_softc *sc = arg0; envsys_data_t *edata = arg1; uint32_t descs[4]; + uint64_t msr; + if (rdmsr_safe(sc->sc_temp_msr, &msr) == EFAULT) { + edata->value_cur = 0; + edata->state = ENVSYS_SINVALID; + aprint_error_dev(sc->sc_dev, "Reading temperature failed\n"); + return; + } x86_cpuid(0xc0000002, descs); + aprint_normal_dev(sc->sc_dev, "CPUID reported temp %d\n", descs[0] >> 8); - edata->value_cur = descs[0] >> 8; + /* Lower 24-bits hold value in Celsius */ + edata->value_cur = msr & 0xffffff; edata->value_cur *= 1000000; edata->value_cur += 273150000; edata->state = ENVSYS_SVALID; } +static uint32_t viac7temp_msr_register(struct cpu_info *ci) +{ + uint32_t family, model; + uint32_t reg; + + reg = 0; + model = CPUID_TO_MODEL(ci->ci_signature); + family = CPUID_TO_FAMILY(ci->ci_signature); + + if (family == 0x07 || (family == 0x06 && model >= 0x0f)) + reg = MSR_TEMP_NANO; + else if (family == 0x06 && model > 0x09) + reg = MSR_TEMP_C7; + + return reg; +} + MODULE(MODULE_CLASS_DRIVER, viac7temp, NULL); #ifdef _MODULE