-/* $OpenBSD: identcpu.c,v 1.122 2022/01/20 11:06:57 bluhm Exp $ */
+/* $OpenBSD: identcpu.c,v 1.123 2022/04/26 08:35:30 claudio Exp $ */
/* $NetBSD: identcpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
/*
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/atomic.h>
+#include <sys/proc.h>
#include <sys/sysctl.h>
#include "vmm.h"
}
#ifndef SMALL_KERNEL
-void intelcore_update_sensor(void *args);
+void intelcore_update_sensor(void *);
+void cpu_hz_update_sensor(void *);
+
/*
* Temperature read on the CPU is relative to the maximum
* temperature supported by the CPU, Tj(Max).
}
}
+/*
+ * Effective CPU frequency measurement
+ *
+ * Refer to:
+ * 64-ia-32-architectures-software-developer-vol-3b-part-2-manual.pdf
+ * Section 14.2 and
+ * OSRR for AMD Family 17h processors Section 2.1.2
+ * Round to 50Mhz which is the accuracy of this measurement.
+ */
+#define FREQ_50MHZ (50ULL * 1000000ULL * 1000000ULL)
+void
+cpu_hz_update_sensor(void *args)
+{
+ extern uint64_t tsc_frequency;
+ struct cpu_info *ci = args;
+ uint64_t mperf, aperf, mdelta, adelta, val;
+ unsigned long s;
+
+ sched_peg_curproc(ci);
+
+ s = intr_disable();
+ mperf = rdmsr(MSR_MPERF);
+ aperf = rdmsr(MSR_APERF);
+ intr_restore(s);
+
+ mdelta = mperf - ci->ci_hz_mperf;
+ adelta = aperf - ci->ci_hz_aperf;
+ ci->ci_hz_mperf = mperf;
+ ci->ci_hz_aperf = aperf;
+
+ if (mdelta > 0) {
+ val = (adelta * 1000000) / mdelta * tsc_frequency;
+ val = ((val + FREQ_50MHZ / 2) / FREQ_50MHZ) * FREQ_50MHZ;
+ ci->ci_hz_sensor.value = val;
+ }
+
+ atomic_clearbits_int(&curproc->p_flag, P_CPUPEG);
+}
#endif
void (*setperf_setup)(struct cpu_info *);
identifycpu(struct cpu_info *ci)
{
uint64_t freq = 0;
- u_int32_t dummy, val;
+ u_int32_t dummy, val, cpu_tpm_ecxflags = 0;
char mycpu_model[48];
int i;
char *brandstr_from, *brandstr_to;
}
if (!strcmp(cpu_vendor, "GenuineIntel") && cpuid_level >= 0x06) {
- CPUID(0x06, ci->ci_feature_tpmflags, dummy, dummy, dummy);
+ CPUID(0x06, ci->ci_feature_tpmflags, dummy, cpu_tpm_ecxflags,
+ dummy);
for (i = 0; i < nitems(cpu_tpm_eaxfeatures); i++)
if (ci->ci_feature_tpmflags &
cpu_tpm_eaxfeatures[i].bit)
printf(",%s", cpu_tpm_eaxfeatures[i].str);
} else if (!strcmp(cpu_vendor, "AuthenticAMD")) {
+ CPUID(0x06, ci->ci_feature_tpmflags, dummy, cpu_tpm_ecxflags,
+ dummy);
if (ci->ci_family >= 0x12)
ci->ci_feature_tpmflags |= TPM_ARAT;
}
#ifndef SMALL_KERNEL
if (CPU_IS_PRIMARY(ci) && (ci->ci_feature_tpmflags & TPM_SENSOR)) {
- strlcpy(ci->ci_sensordev.xname, ci->ci_dev->dv_xname,
- sizeof(ci->ci_sensordev.xname));
ci->ci_sensor.type = SENSOR_TEMP;
sensor_task_register(ci, intelcore_update_sensor, 5);
sensor_attach(&ci->ci_sensordev, &ci->ci_sensor);
- sensordev_install(&ci->ci_sensordev);
}
#endif
if (CPU_IS_PRIMARY(ci) && !strcmp(cpu_vendor, "CentaurHauls")) {
ci->cpu_setup = via_nano_setup;
#ifndef SMALL_KERNEL
- strlcpy(ci->ci_sensordev.xname, ci->ci_dev->dv_xname,
- sizeof(ci->ci_sensordev.xname));
ci->ci_sensor.type = SENSOR_TEMP;
sensor_task_register(ci, via_update_sensor, 5);
sensor_attach(&ci->ci_sensordev, &ci->ci_sensor);
- sensordev_install(&ci->ci_sensordev);
#endif
}
#if NVMM > 0
cpu_check_vmm_cap(ci);
#endif /* NVMM > 0 */
+
+ /* Check for effective frequency via MPERF, APERF */
+ if ((cpu_tpm_ecxflags & TPM_EFFFREQ) &&
+ ci->ci_smt_id == 0) {
+#ifndef SMALL_KERNEL
+ ci->ci_hz_sensor.type = SENSOR_FREQ;
+ sensor_task_register(ci, cpu_hz_update_sensor, 1);
+ sensor_attach(&ci->ci_sensordev, &ci->ci_hz_sensor);
+#endif
+ }
}
#ifndef SMALL_KERNEL
-/* $OpenBSD: specialreg.h,v 1.91 2021/11/19 04:00:53 guenther Exp $ */
+/* $OpenBSD: specialreg.h,v 1.92 2022/04/26 08:35:30 claudio Exp $ */
/* $NetBSD: specialreg.h,v 1.1 2003/04/26 18:39:48 fvdl Exp $ */
/* $NetBSD: x86/specialreg.h,v 1.2 2003/04/25 21:54:30 fvdl Exp $ */
*/
#define TPM_SENSOR 0x00000001 /* Digital temp sensor */
#define TPM_ARAT 0x00000004 /* APIC Timer Always Running */
+/* Thermal and Power Management (CPUID function 0x6) ECX bits */
+#define TPM_EFFFREQ 0x00000001 /* APERF & MPERF MSR present */
/*
* "Architectural Performance Monitoring" bits (CPUID function 0x0a):
#define MSR_PERFCTR0 0x0c1
#define MSR_PERFCTR1 0x0c2
#define MSR_FSB_FREQ 0x0cd /* Core Duo/Solo only */
+#define MSR_MPERF 0x0e7
+#define MSR_APERF 0x0e8
#define MSR_MTRRcap 0x0fe
#define MTRRcap_FIXED 0x100 /* bit 8 - fixed MTRRs supported */
#define MTRRcap_WC 0x400 /* bit 10 - WC type supported */