Index: sys/arch/amd64/conf/GENERIC =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/conf/GENERIC,v retrieving revision 1.216 diff -u -p -r1.216 GENERIC --- sys/arch/amd64/conf/GENERIC 26 May 2008 00:33:37 -0000 1.216 +++ sys/arch/amd64/conf/GENERIC 22 Jul 2008 05:27:25 -0000 @@ -259,8 +259,8 @@ options ACPI_SCANPCI # find PCI roots options MPBIOS # configure CPUs and APICs using MPBIOS options MPBIOS_SCANPCI # MPBIOS configures PCI roots #options PCI_INTR_FIXUP # PCI interrupt routing via ACPI -#options PCI_BUS_FIXUP # fixup PCI bus numbering -#options PCI_ADDR_FIXUP # fixup PCI I/O addresses +options PCI_BUS_FIXUP # fixup PCI bus numbering +options PCI_ADDR_FIXUP # fixup PCI I/O addresses #options ACPI_ACTIVATE_DEV # If set, activate inactive devices #options ACPICA_PEDANTIC # force strict conformance to the Spec. Index: sys/arch/x86/include/powernow.h =================================================================== RCS file: /cvsroot/src/sys/arch/x86/include/powernow.h,v retrieving revision 1.9 diff -u -p -r1.9 powernow.h --- sys/arch/x86/include/powernow.h 24 Mar 2007 15:35:15 -0000 1.9 +++ sys/arch/x86/include/powernow.h 22 Jul 2008 05:27:30 -0000 @@ -70,6 +70,10 @@ */ #define MSR_AMDK7_FIDVID_CTL 0xc0010041 #define MSR_AMDK7_FIDVID_STATUS 0xc0010042 +#define MSR_AMDK10_PSTATE_LIMIT 0xc0010061 +#define MSR_AMDK10_PSTATE_CTL 0xc0010062 +#define MSR_AMDK10_PSTATE_STATUS 0xc0010063 +#define MSR_AMDK10_PSTATE_BASE 0xc0010064 #define AMD_PN_FID_VID 0x06 #define AMD_ERRATA_A0_CPUSIG 0x660 @@ -171,6 +175,7 @@ struct powernow_pst_s { }; int powernow_probe(struct cpu_info *); +int powernow_probe_k10(struct cpu_info *); /* i386/i386/powernow_k7.c */ void k7_powernow_init(void); @@ -180,4 +185,7 @@ void k7_powernow_destroy(void); void k8_powernow_init(void); void k8_powernow_destroy(void); +/* x86/x86/powernow_k8.c */ +void k10_powernow_init(void); + #endif Index: sys/arch/x86/x86/identcpu.c =================================================================== RCS file: /cvsroot/src/sys/arch/x86/x86/identcpu.c,v retrieving revision 1.9 diff -u -p -r1.9 identcpu.c --- sys/arch/x86/x86/identcpu.c 2 Jun 2008 14:41:41 -0000 1.9 +++ sys/arch/x86/x86/identcpu.c 22 Jul 2008 05:27:30 -0000 @@ -783,6 +783,8 @@ cpu_identify(struct cpu_info *ci) break; } } + else if (cpu_vendor == CPUVENDOR_AMD && powernow_probe_k10(ci)) + k10_powernow_init(); #endif /* POWERNOW_K7 || POWERNOW_K8 */ #ifdef INTEL_ONDEMAND_CLOCKMOD Index: sys/arch/x86/x86/powernow_common.c =================================================================== RCS file: /cvsroot/src/sys/arch/x86/x86/powernow_common.c,v retrieving revision 1.11 diff -u -p -r1.11 powernow_common.c --- sys/arch/x86/x86/powernow_common.c 21 May 2008 01:13:07 -0000 1.11 +++ sys/arch/x86/x86/powernow_common.c 22 Jul 2008 05:27:30 -0000 @@ -55,3 +55,16 @@ powernow_probe(struct cpu_info *ci) return (regs[3] & AMD_PN_FID_VID) == AMD_PN_FID_VID; } + +int +powernow_probe_k10(struct cpu_info *ci) +{ + uint32_t regs[4]; + + x86_cpuid(0x80000000, regs); + if (regs[0] < 0x80000007) + return 0; + x86_cpuid(0x80000007, regs); + + return (regs[3] & 0x00000080) == 0x00000080; +} Index: sys/arch/x86/x86/powernow_k8.c =================================================================== RCS file: /cvsroot/src/sys/arch/x86/x86/powernow_k8.c,v retrieving revision 1.23 diff -u -p -r1.23 powernow_k8.c --- sys/arch/x86/x86/powernow_k8.c 11 May 2008 23:05:45 -0000 1.23 +++ sys/arch/x86/x86/powernow_k8.c 22 Jul 2008 05:27:30 -0000 @@ -110,6 +110,11 @@ static int k8_powernow_setperf(unsigned static int k8_powernow_init_once(void); static void k8_powernow_init_main(void); +static int k10pnow_sysctl_helper(SYSCTLFN_PROTO); +static void k10_powernow_setperf(int); +static int k10_powernow_init_once(void); +static void k10_powernow_init_main(void); + static int k8pnow_sysctl_helper(SYSCTLFN_ARGS) { @@ -494,3 +499,86 @@ k8_powernow_destroy(void) free(freq_names, M_SYSCTLDATA); #endif } + +static int +k10pnow_sysctl_helper(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + int error, opstate, pstate; + + opstate = pstate = (int)(rdmsr(MSR_AMDK10_PSTATE_STATUS) & 7); + + node = *rnode; + node.sysctl_data = &pstate; + + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return error; + +#define MAX_PSTATES 4 /* for Opteron 1352 on Dell PowerEdge T105 BIOS v1.2.1 */ + if (pstate < 0 || pstate > MAX_PSTATES) + return EINVAL; + + if (pstate != opstate) + k10_powernow_setperf(pstate); + + *(int *)node.sysctl_data = pstate; + + return 0; +} + +static void +k10_powernow_setperf(int pstate) +{ + wrmsr(MSR_AMDK10_PSTATE_CTL, pstate); + return; +} + +static int +k10_powernow_init_once(void) +{ + k10_powernow_init_main(); + return 0; +} + +void +k10_powernow_init(void) +{ + int error; + static ONCE_DECL(powernow_initialized); + + error = RUN_ONCE(&powernow_initialized, k10_powernow_init_once); + if (__predict_false(error != 0)) { + return; + } +} + +static void +k10_powernow_init_main(void) +{ + uint64_t status; + const struct sysctlnode *pstatenode, *node, *pnownode; + int fid, div, i; + + for (i = 0; i <= MAX_PSTATES; i++) { + status = rdmsr(MSR_AMDK10_PSTATE_BASE + i); + fid = (int)(status & 0x3f); + div = (int)((status >> 6) & 7); + printf("%s: pstate %d: %dMHz\n", __func__, i, + (100 * (fid + 16)) >> div); + } + + sysctl_createv(SYSCTLLOG, 0, NULL, &node, CTLFLAG_PERMANENT, + CTLTYPE_NODE, "machdep", NULL, NULL, 0, NULL, 0, + CTL_MACHDEP, CTL_EOL); + + sysctl_createv(SYSCTLLOG, 0, &node, &pnownode, 0, + CTLTYPE_NODE, "powernow_k10", NULL, NULL, 0, NULL, 0, + CTL_CREATE, CTL_EOL); + + sysctl_createv(SYSCTLLOG, 0, &pnownode, &pstatenode, CTLFLAG_READWRITE, + CTLTYPE_INT, "pstate", NULL, k10pnow_sysctl_helper, 0, NULL, 0, + CTL_CREATE, CTL_EOL); + + return; +}