Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Add native support for AMD family 0Fh processors. This is th...



details:   https://anonhg.NetBSD.org/src/rev/911a1fa28e7c
branches:  trunk
changeset: 757293:911a1fa28e7c
user:      jruoho <jruoho%NetBSD.org@localhost>
date:      Tue Aug 24 07:27:59 2010 +0000

description:
Add native support for AMD family 0Fh processors. This is the furthest we
will go backwards; K7 will not be supported already due doubts about
availability and reliability of ACPI during that era. Some unfortunate code
duplication is present (but not overly much). Thanks to cegger@ and jakllsch@
for patiently testing this.

diffstat:

 share/man/man4/acpicpu.4        |   36 ++--
 sys/arch/x86/acpi/acpi_cpu_md.c |  275 +++++++++++++++++++++++++++++++++++++--
 sys/dev/acpi/acpi_cpu.h         |    7 +-
 3 files changed, 282 insertions(+), 36 deletions(-)

diffs (truncated from 513 to 300 lines):

diff -r 28151101529a -r 911a1fa28e7c share/man/man4/acpicpu.4
--- a/share/man/man4/acpicpu.4  Tue Aug 24 05:34:15 2010 +0000
+++ b/share/man/man4/acpicpu.4  Tue Aug 24 07:27:59 2010 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: acpicpu.4,v 1.14 2010/08/20 06:35:55 jruoho Exp $
+.\" $NetBSD: acpicpu.4,v 1.15 2010/08/24 07:27:59 jruoho Exp $
 .\"
 .\" Coyright (c) 2010 Jukka Ruohonen <jruohonen%iki.fi@localhost>
 .\" All rights reserved.
@@ -24,7 +24,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd August 20, 2010
+.Dd August 24, 2010
 .Dt ACPICPU 4
 .Os
 .Sh NAME
@@ -161,12 +161,17 @@
 .Dq PowerSaver
 .Pq VIA .
 .Pp
-The
-.Dv P0
-state is always the highest operating frequency supported by the processor.
+The P0-state is always the highest operating
+frequency supported by the processor.
 The number of additional P-states may vary across processors and vendors.
 Each higher numbered P-state represents lower
 clock frequencies and hence lower power consumption.
+Note that while
+.Nm
+always uses the exact frequencies internally,
+the user-visible values reported by
+.Tn ACPI
+may be rounded or approximated by the vendor.
 .Pp
 Unlike conventional
 .Tn CPU
@@ -174,8 +179,9 @@
 .Tn ACPI
 provides support for Dynamic Voltage and Frequency Scaling
 .Pq Tn DVFS .
-This means that the firmware may request the implementation to
-dynamically scale the presently supported maximum clock frequency.
+Among other things,
+this means that the firmware may request the implementation to
+dynamically scale the presently supported maximum or minimum clock frequency.
 For example, if
 .Xr acpiacad 4
 is disconnected, the maximum available frequency may be lowered.
@@ -191,7 +197,7 @@
 time a processor is allowed to execute.
 Outside the
 .Tn ACPI
-nomenclature, throttling may be known as
+nomenclature, throttling and T-states may be known as
 .Dq on-demand clock modulation
 .Pq Tn ODCM .
 .Pp
@@ -205,8 +211,7 @@
 and thus, comparable to the C0-state, the processor is fully active.
 Each additional higher-numbered T-state indicates lower duty cycles.
 At most eight T-states may be available, although also T-states use
-.Tn DVFS ;
-both the maximum and the minimum available T-state may change dynamically.
+.Tn DVFS .
 .Pp
 The duty cycle does not refer to the actual clock signal,
 but to the time period in which the clock signal is allowed
@@ -218,7 +223,7 @@
 .Tn CPU
 is forced to idle.
 Because of this, the use of T-states may
-severely reduce system performance.
+severely affect system performance.
 .Pp
 There are two typical situations for throttling:
 power management and thermal control.
@@ -266,7 +271,7 @@
 .Dv ENHANCED_SPEEDSTEP
 and
 .Dv POWERNOW_K8 .
-Depending on the processor vendor, the second-level node is either
+Depending on the processor, the second-level node is either
 .Ic machdep.est
 or
 .Ic machdep.powernow .
@@ -299,9 +304,6 @@
 .An Jukka Ruohonen
 .Aq jruohonen%iki.fi@localhost
 .Sh CAVEATS
-The
-.Nm
-driver should be considered experimental.
 At least the following caveats can be mentioned.
 .Bl -bullet
 .It
@@ -320,10 +322,6 @@
 it is recommended to turn it off, with or without
 .Nm .
 .It
-While P-states are supported on all Intel
-.Tn CPUs ,
-not all AMD processors are yet supported.
-.It
 Processor thermal control (see
 .Xr acpitz 4 )
 is not yet supported.
diff -r 28151101529a -r 911a1fa28e7c sys/arch/x86/acpi/acpi_cpu_md.c
--- a/sys/arch/x86/acpi/acpi_cpu_md.c   Tue Aug 24 05:34:15 2010 +0000
+++ b/sys/arch/x86/acpi/acpi_cpu_md.c   Tue Aug 24 07:27:59 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu_md.c,v 1.31 2010/08/23 16:20:44 jruoho Exp $ */
+/* $NetBSD: acpi_cpu_md.c,v 1.32 2010/08/24 07:28:00 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2010 Jukka Ruohonen <jruohonen%iki.fi@localhost>
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.31 2010/08/23 16:20:44 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.32 2010/08/24 07:28:00 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -48,21 +48,53 @@
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcidevs.h>
 
-#define CPUID_INTEL_TSC                __BIT(8)
-
-#define MSR_0FH_CONTROL                0xc0010041 /* Family 0Fh (and K7).  */
-#define MSR_0FH_STATUS         0xc0010042
-
-#define MSR_10H_LIMIT          0xc0010061 /* Families 10h and 11h. */
+/*
+ * AMD families 10h and 11h.
+ */
+#define MSR_10H_LIMIT          0xc0010061
 #define MSR_10H_CONTROL                0xc0010062
 #define MSR_10H_STATUS         0xc0010063
 #define MSR_10H_CONFIG         0xc0010064
 
+/*
+ * AMD family 0Fh.
+ */
+#define MSR_0FH_CONTROL                0xc0010041
+#define MSR_0FH_STATUS         0xc0010042
+
+#define MSR_0FH_STATUS_CFID    __BITS( 0,  5)
+#define MSR_0FH_STATUS_CVID    __BITS(32, 36)
+#define MSR_0FH_STATUS_PENDING __BITS(31, 31)
+
+#define MSR_0FH_CONTROL_FID    __BITS( 0,  5)
+#define MSR_0FH_CONTROL_VID    __BITS( 8, 12)
+#define MSR_0FH_CONTROL_CHG    __BITS(16, 16)
+#define MSR_0FH_CONTROL_CNT    __BITS(32, 51)
+
+#define ACPI_0FH_STATUS_FID    __BITS( 0,  5)
+#define ACPI_0FH_STATUS_VID    __BITS( 6, 10)
+
+#define ACPI_0FH_CONTROL_FID   __BITS( 0,  5)
+#define ACPI_0FH_CONTROL_VID   __BITS( 6, 10)
+#define ACPI_0FH_CONTROL_VST   __BITS(11, 17)
+#define ACPI_0FH_CONTROL_MVS   __BITS(18, 19)
+#define ACPI_0FH_CONTROL_PLL   __BITS(20, 26)
+#define ACPI_0FH_CONTROL_RVO   __BITS(28, 29)
+#define ACPI_0FH_CONTROL_IRT   __BITS(30, 31)
+
+#define FID_TO_VCO_FID(fidd)   (((fid) < 8) ? (8 + ((fid) << 1)) : (fid))
+
 static char      native_idle_text[16];
 void           (*native_idle)(void) = NULL;
 
 static int      acpicpu_md_quirks_piix4(struct pci_attach_args *);
 static void     acpicpu_md_pstate_status(void *, void *);
+static int      acpicpu_md_pstate_fidvid_get(struct acpicpu_softc *,
+                                              uint32_t *);
+static int      acpicpu_md_pstate_fidvid_set(struct acpicpu_pstate *);
+static int      acpicpu_md_pstate_fidvid_read(uint32_t *, uint32_t *);
+static void     acpicpu_md_pstate_fidvid_write(uint32_t, uint32_t,
+                                               uint32_t, uint32_t);
 static void     acpicpu_md_tstate_status(void *, void *);
 static int      acpicpu_md_pstate_sysctl_init(void);
 static int      acpicpu_md_pstate_sysctl_get(SYSCTLFN_PROTO);
@@ -178,7 +210,7 @@
 
                        x86_cpuid(0x80000007, regs);
 
-                       if ((regs[3] & CPUID_INTEL_TSC) != 0)
+                       if ((regs[3] & __BIT(8)) != 0)
                                val &= ~ACPICPU_FLAG_C_TSC;
                }
 
@@ -186,19 +218,34 @@
 
        case CPUVENDOR_AMD:
 
+               x86_cpuid(0x80000000, regs);
+
+               if (regs[0] < 0x80000007)
+                       break;
+
+               x86_cpuid(0x80000007, regs);
+
                family = CPUID2FAMILY(ci->ci_signature);
 
                if (family == 0xf)
                        family += CPUID2EXTFAMILY(ci->ci_signature);
 
-               switch (family) {
+               switch (family) {
 
                case 0x0f:
+
+                       if ((regs[3] & CPUID_APM_FID) == 0)
+                               break;
+
+                       if ((regs[3] & CPUID_APM_VID) == 0)
+                               break;
+
+                       val |= ACPICPU_FLAG_P_FFH | ACPICPU_FLAG_P_FIDVID;
+                       break;
+
                case 0x10:
                case 0x11:
 
-                       x86_cpuid(0x80000007, regs);
-
                        if ((regs[3] & CPUID_APM_TSC) != 0)
                                val &= ~ACPICPU_FLAG_C_TSC;
 
@@ -370,6 +417,9 @@
 
        (void)memset(&msr, 0, sizeof(struct acpicpu_pstate));
 
+       if ((sc->sc_flags & ACPICPU_FLAG_P_FIDVID) != 0)
+               msr.ps_flags = ACPICPU_FLAG_P_FIDVID;
+
        switch (cpu_vendor) {
 
        case CPUVENDOR_IDT:
@@ -390,6 +440,11 @@
 
                switch (family) {
 
+               case 0x0f:
+                       msr.ps_control_addr = MSR_0FH_CONTROL;
+                       msr.ps_status_addr  = MSR_0FH_STATUS;
+                       break;
+
                case 0x10:
                case 0x11:
                        msr.ps_control_addr = MSR_10H_CONTROL;
@@ -421,6 +476,9 @@
 
                ps = &sc->sc_pstate[i];
 
+               if (msr.ps_flags != 0)
+                       ps->ps_flags |= msr.ps_flags;
+
                if (msr.ps_status_addr != 0)
                        ps->ps_status_addr = msr.ps_status_addr;
 
@@ -466,11 +524,14 @@
        uint64_t val;
        uint32_t i;
 
+       if ((sc->sc_flags & ACPICPU_FLAG_P_FIDVID) != 0)
+               return acpicpu_md_pstate_fidvid_get(sc, freq);
+
        for (i = 0; i < sc->sc_pstate_count; i++) {
 
                ps = &sc->sc_pstate[i];
 
-               if (ps->ps_freq != 0)
+               if (__predict_true(ps->ps_freq != 0))
                        break;
        }
 
@@ -489,7 +550,7 @@
 
                ps = &sc->sc_pstate[i];
 
-               if (ps->ps_freq == 0)
+               if (__predict_false(ps->ps_freq == 0))
                        continue;
 
                if (val == ps->ps_status) {
@@ -508,6 +569,9 @@
        uint64_t xc;
        int rv = 0;
 
+       if ((ps->ps_flags & ACPICPU_FLAG_P_FIDVID) != 0)
+               return acpicpu_md_pstate_fidvid_set(ps);
+
        msr.msr_read  = false;
        msr.msr_type  = ps->ps_control_addr;



Home | Main Index | Thread Index | Old Index