--- a/sys/dev/powermng/coretemp/coretemp.c +++ b/sys/dev/powermng/coretemp/coretemp.c @@ -133,7 +133,7 @@ static int coretemp_attach(device_t dev); static int coretemp_detach(device_t dev); -static void coretemp_msr_fetch(struct coretemp_softc *sc, uint64_t *msr, +static int coretemp_msr_fetch(struct coretemp_softc *sc, uint64_t *msr, uint64_t *pkg_msr); static int coretemp_msr_temp(struct coretemp_softc *sc, uint64_t msr); static void coretemp_sensor_update(struct coretemp_softc *sc, int temp); @@ -589,16 +589,30 @@ return temp; } -static void +static int coretemp_msr_fetch(struct coretemp_softc *sc, uint64_t *msr, uint64_t *pkg_msr) { + int error; + KASSERT(sc->sc_cpu == mycpuid, ("%s not on the target cpu%d, but on %d", device_get_name(sc->sc_dev), sc->sc_cpu, mycpuid)); - *msr = rdmsr(MSR_THERM_STATUS); - if (pkg_msr != NULL) - *pkg_msr = rdmsr(MSR_PKG_THERM_STATUS); + /* + * NB: some CPUs and VMMs advertise the CPUID thermal/DTS bits + * without actually implementing the MSRs (see the PIII comment + * in coretemp_identify()). Use the fault-safe read so a lying + * CPUID degrades to an invalid sensor instead of a kernel #GP. + */ + error = rdmsr_safe(MSR_THERM_STATUS, msr); + if (error) + return error; + if (pkg_msr != NULL) { + error = rdmsr_safe(MSR_PKG_THERM_STATUS, pkg_msr); + if (error) + return error; + } + return 0; } static void @@ -647,7 +661,10 @@ uint64_t msr; int temp; - coretemp_msr_fetch(sc, &msr, NULL); + if (coretemp_msr_fetch(sc, &msr, NULL) != 0) { + coretemp_sensor_update(sc, CORETEMP_TEMP_INVALID); + return; + } temp = coretemp_msr_temp(sc, msr); coretemp_sensor_update(sc, temp); @@ -660,7 +677,11 @@ uint64_t msr, pkg_msr; int temp, pkg_temp; - coretemp_msr_fetch(sc, &msr, &pkg_msr); + if (coretemp_msr_fetch(sc, &msr, &pkg_msr) != 0) { + coretemp_sensor_update(sc, CORETEMP_TEMP_INVALID); + coretemp_pkg_sensor_update(sc, CORETEMP_TEMP_INVALID); + return; + } temp = coretemp_msr_temp(sc, msr); pkg_temp = coretemp_pkg_msr_temp(sc, pkg_msr);