Module Name:    src
Committed By:   jruoho
Date:           Fri Feb 25 09:16:00 UTC 2011

Modified Files:
        src/sys/arch/x86/acpi: acpi_cpu_md.c
        src/sys/dev/acpi: acpi_cpu.h acpi_cpu_pstate.c

Log Message:
Add preliminary support for the IA32_APERF and IA32_MPERF frequency counters.
These are not yet used for anything and only Intel is supported at the moment.


To generate a diff of this commit:
cvs rdiff -u -r1.40 -r1.41 src/sys/arch/x86/acpi/acpi_cpu_md.c
cvs rdiff -u -r1.29 -r1.30 src/sys/dev/acpi/acpi_cpu.h
cvs rdiff -u -r1.38 -r1.39 src/sys/dev/acpi/acpi_cpu_pstate.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x86/acpi/acpi_cpu_md.c
diff -u src/sys/arch/x86/acpi/acpi_cpu_md.c:1.40 src/sys/arch/x86/acpi/acpi_cpu_md.c:1.41
--- src/sys/arch/x86/acpi/acpi_cpu_md.c:1.40	Thu Feb 24 13:19:36 2011
+++ src/sys/arch/x86/acpi/acpi_cpu_md.c	Fri Feb 25 09:16:00 2011
@@ -1,7 +1,7 @@
-/* $NetBSD: acpi_cpu_md.c,v 1.40 2011/02/24 13:19:36 jmcneill Exp $ */
+/* $NetBSD: acpi_cpu_md.c,v 1.41 2011/02/25 09:16:00 jruoho Exp $ */
 
 /*-
- * Copyright (c) 2010 Jukka Ruohonen <jruoho...@iki.fi>
+ * Copyright (c) 2010, 2011 Jukka Ruohonen <jruoho...@iki.fi>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.40 2011/02/24 13:19:36 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.41 2011/02/25 09:16:00 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -99,6 +99,8 @@
 void		(*native_idle)(void) = NULL;
 
 static int	 acpicpu_md_quirks_piix4(struct pci_attach_args *);
+static void	 acpicpu_md_pstate_percent_reset(struct acpicpu_softc *);
+static void	 acpicpu_md_pstate_percent_status(void *, void *);
 static void	 acpicpu_md_pstate_status(void *, void *);
 static int	 acpicpu_md_pstate_fidvid_get(struct acpicpu_softc *,
                                               uint32_t *);
@@ -408,16 +410,22 @@
 }
 
 int
-acpicpu_md_pstate_start(void)
+acpicpu_md_pstate_start(struct acpicpu_softc *sc)
 {
 	const uint64_t est = __BIT(16);
 	uint64_t val;
 
+	if ((sc->sc_flags & ACPICPU_FLAG_P) == 0)
+		return ENODEV;
+
 	switch (cpu_vendor) {
 
 	case CPUVENDOR_IDT:
 	case CPUVENDOR_INTEL:
 
+		/*
+		 * Make sure EST is enabled.
+		 */
 		val = rdmsr(MSR_MISC_ENABLE);
 
 		if ((val & est) == 0) {
@@ -430,6 +438,12 @@
 			if ((val & est) == 0)
 				return ENOTTY;
 		}
+
+		/*
+		 * Reset the APERF and MPERF counters.
+		 */
+		if ((sc->sc_flags & ACPICPU_FLAG_P_HW) != 0)
+			acpicpu_md_pstate_percent_reset(sc);
 	}
 
 	return acpicpu_md_pstate_sysctl_init();
@@ -549,6 +563,80 @@
 	return 0;
 }
 
+/*
+ * Returns the percentage of the actual frequency in
+ * terms of the maximum frequency of the calling CPU
+ * since the last call. A value zero implies an error.
+ */
+uint8_t
+acpicpu_md_pstate_percent(struct acpicpu_softc *sc)
+{
+	struct cpu_info *ci = sc->sc_ci;
+	uint64_t aperf, mperf;
+	uint64_t xc, rv = 0;
+
+	if (__predict_false((sc->sc_flags & ACPICPU_FLAG_P) == 0))
+		return 0;
+
+	if (__predict_false((sc->sc_flags & ACPICPU_FLAG_P_HW) == 0))
+		return 0;
+
+	/*
+	 * Read the IA32_APERF and IA32_MPERF counters. The first
+	 * increments at the rate of the fixed maximum frequency
+	 * configured during the boot, whereas APERF counts at the
+	 * rate of the actual frequency. Note that the MSRs must be
+	 * read without delay, and that only the ratio between
+	 * IA32_APERF and IA32_MPERF is architecturally defined.
+	 *
+	 * For further details, refer to:
+	 *
+	 *	Intel Corporation: Intel 64 and IA-32 Architectures
+	 *	Software Developer's Manual. Section 13.2, Volume 3A:
+	 *	System Programming Guide, Part 1. July, 2008.
+	 */
+	x86_disable_intr();
+
+	aperf = sc->sc_pstate_aperf;
+	mperf = sc->sc_pstate_mperf;
+
+	xc = xc_unicast(0, acpicpu_md_pstate_percent_status, sc, NULL, ci);
+	xc_wait(xc);
+
+	x86_enable_intr();
+
+	aperf = sc->sc_pstate_aperf - aperf;
+	mperf = sc->sc_pstate_mperf - mperf;
+
+	if (__predict_true(mperf != 0))
+		rv = (aperf * 100) / mperf;
+
+	return rv;
+}
+
+static void
+acpicpu_md_pstate_percent_status(void *arg1, void *arg2)
+{
+	struct acpicpu_softc *sc = arg1;
+
+	sc->sc_pstate_aperf = rdmsr(MSR_APERF);
+	sc->sc_pstate_mperf = rdmsr(MSR_MPERF);
+}
+
+static void
+acpicpu_md_pstate_percent_reset(struct acpicpu_softc *sc)
+{
+
+	KASSERT((sc->sc_flags & ACPICPU_FLAG_P) != 0);
+	KASSERT((sc->sc_flags & ACPICPU_FLAG_P_HW) != 0);
+
+	wrmsr(MSR_APERF, 0);
+	wrmsr(MSR_MPERF, 0);
+
+	sc->sc_pstate_aperf = 0;
+	sc->sc_pstate_mperf = 0;
+}
+
 int
 acpicpu_md_pstate_get(struct acpicpu_softc *sc, uint32_t *freq)
 {

Index: src/sys/dev/acpi/acpi_cpu.h
diff -u src/sys/dev/acpi/acpi_cpu.h:1.29 src/sys/dev/acpi/acpi_cpu.h:1.30
--- src/sys/dev/acpi/acpi_cpu.h:1.29	Fri Feb 25 06:18:02 2011
+++ src/sys/dev/acpi/acpi_cpu.h	Fri Feb 25 09:16:00 2011
@@ -1,7 +1,7 @@
-/* $NetBSD: acpi_cpu.h,v 1.29 2011/02/25 06:18:02 jruoho Exp $ */
+/* $NetBSD: acpi_cpu.h,v 1.30 2011/02/25 09:16:00 jruoho Exp $ */
 
 /*-
- * Copyright (c) 2010 Jukka Ruohonen <jruoho...@iki.fi>
+ * Copyright (c) 2010, 2011 Jukka Ruohonen <jruoho...@iki.fi>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -188,6 +188,8 @@
 	struct acpicpu_pstate	*sc_pstate;
 	struct acpicpu_reg	 sc_pstate_control;
 	struct acpicpu_reg	 sc_pstate_status;
+	uint64_t		 sc_pstate_aperf;	/* ACPICPU_FLAG_P_HW */
+	uint64_t		 sc_pstate_mperf;	/* ACPICPU_FLAG_P_HW*/
 	uint32_t		 sc_pstate_current;
 	uint32_t		 sc_pstate_count;
 	uint32_t		 sc_pstate_max;
@@ -239,9 +241,10 @@
 int		acpicpu_md_idle_start(struct acpicpu_softc *);
 int		acpicpu_md_idle_stop(void);
 void		acpicpu_md_idle_enter(int, int);
-int		acpicpu_md_pstate_start(void);
+int		acpicpu_md_pstate_start(struct acpicpu_softc *);
 int		acpicpu_md_pstate_stop(void);
 int		acpicpu_md_pstate_pss(struct acpicpu_softc *);
+uint8_t		acpicpu_md_pstate_percent(struct acpicpu_softc *);
 int		acpicpu_md_pstate_get(struct acpicpu_softc *, uint32_t *);
 int		acpicpu_md_pstate_set(struct acpicpu_pstate *);
 int		acpicpu_md_tstate_get(struct acpicpu_softc *, uint32_t *);

Index: src/sys/dev/acpi/acpi_cpu_pstate.c
diff -u src/sys/dev/acpi/acpi_cpu_pstate.c:1.38 src/sys/dev/acpi/acpi_cpu_pstate.c:1.39
--- src/sys/dev/acpi/acpi_cpu_pstate.c:1.38	Wed Feb 23 06:17:55 2011
+++ src/sys/dev/acpi/acpi_cpu_pstate.c	Fri Feb 25 09:16:00 2011
@@ -1,7 +1,7 @@
-/* $NetBSD: acpi_cpu_pstate.c,v 1.38 2011/02/23 06:17:55 jruoho Exp $ */
+/* $NetBSD: acpi_cpu_pstate.c,v 1.39 2011/02/25 09:16:00 jruoho Exp $ */
 
 /*-
- * Copyright (c) 2010 Jukka Ruohonen <jruoho...@iki.fi>
+ * Copyright (c) 2010, 2011 Jukka Ruohonen <jruoho...@iki.fi>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_pstate.c,v 1.38 2011/02/23 06:17:55 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_pstate.c,v 1.39 2011/02/25 09:16:00 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/evcnt.h>
@@ -249,7 +249,7 @@
 	uint32_t i;
 	int rv;
 
-	rv = acpicpu_md_pstate_start();
+	rv = acpicpu_md_pstate_start(sc);
 
 	if (rv != 0)
 		goto fail;

Reply via email to