Mercurial > illumos > illumos-gate
changeset 938:2d438f28c673
6336786 time doesn't fly when CPUs are not having fun
6347678 lgrp_plat_init() should use routines available from pci_cfgspace.h
author | esaxe |
---|---|
date | Wed, 16 Nov 2005 18:13:48 -0800 |
parents | e808c6c8cf8e |
children | ba7313ba6568 |
files | usr/src/uts/i86pc/Makefile.workarounds usr/src/uts/i86pc/os/cpuid.c usr/src/uts/i86pc/os/lgrpplat.c usr/src/uts/i86pc/os/mp_startup.c |
diffstat | 4 files changed, 70 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/i86pc/Makefile.workarounds Wed Nov 16 17:14:14 2005 -0800 +++ b/usr/src/uts/i86pc/Makefile.workarounds Wed Nov 16 18:13:48 2005 -0800 @@ -90,3 +90,8 @@ # Probe Response # WORKAROUND_DEFS += -DOPTERON_ERRATUM_131 + +# +# TSC may drift when C1-Clock ramping enabled +# +WORKAROUND_DEFS += -DOPTERON_WORKAROUND_6336786
--- a/usr/src/uts/i86pc/os/cpuid.c Wed Nov 16 17:14:14 2005 -0800 +++ b/usr/src/uts/i86pc/os/cpuid.c Wed Nov 16 18:13:48 2005 -0800 @@ -1700,7 +1700,7 @@ cpuid_opteron_erratum(cpu_t *cpu, uint_t erratum) { struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi; - uint_t eax; + uint_t eax, edx, junk; if (cpi->cpi_vendor != X86_VENDOR_AMD) return (0); @@ -1854,7 +1854,16 @@ return (JH_E1(eax) || BH_E4(eax) || JH_E6(eax)); case 131: return (1); - + case 6336786: + /* + * Test for AdvPowerMgmtInfo.TscPStateInvariant + * if this is a K8 family processor + */ + if (CPI_FAMILY(cpi) == 0xf) { + (void) __cpuid_insn(0x80000007, &junk, &junk, &edx); + return (!(edx & 0x100)); + } + return (0); default: return (-1); }
--- a/usr/src/uts/i86pc/os/lgrpplat.c Wed Nov 16 17:14:14 2005 -0800 +++ b/usr/src/uts/i86pc/os/lgrpplat.c Wed Nov 16 18:13:48 2005 -0800 @@ -36,7 +36,8 @@ #include <sys/memlist.h> #include <sys/memnode.h> #include <sys/mman.h> -#include <sys/pci_impl.h> /* for PCI configuration space macros */ +#include <sys/pci_cfgspace.h> +#include <sys/pci_impl.h> #include <sys/param.h> #include <sys/promif.h> /* for prom_printf() */ #include <sys/systm.h> @@ -516,9 +517,8 @@ /* * Read node ID register for node 0 to get node count */ - outl(PCI_CONFADD, PCI_CADDR1(bus, dev, OPT_PCS_FUNC_HT, - OPT_PCS_OFF_NODEID)); - opt_node_info[0] = inl(PCI_CONFDATA); + opt_node_info[0] = pci_getl_func(bus, dev, OPT_PCS_FUNC_HT, + OPT_PCS_OFF_NODEID); lgrp_plat_node_cnt = OPT_NODE_CNT(opt_node_info[0]) + 1; for (node = 0; node < lgrp_plat_node_cnt; node++) { @@ -526,25 +526,22 @@ * Read node ID register (except for node 0 which we just read) */ if (node > 0) { - outl(PCI_CONFADD, PCI_CADDR1(bus, dev, - OPT_PCS_FUNC_HT, OPT_PCS_OFF_NODEID)); - opt_node_info[node] = inl(PCI_CONFDATA); + opt_node_info[node] = pci_getl_func(bus, dev, + OPT_PCS_FUNC_HT, OPT_PCS_OFF_NODEID); } /* * Read DRAM base and limit registers which specify * physical memory range of each node */ - outl(PCI_CONFADD, PCI_CADDR1(bus, dev, OPT_PCS_FUNC_ADDRMAP, - off)); - opt_dram_map[node].base = inl(PCI_CONFDATA); + opt_dram_map[node].base = pci_getl_func(bus, dev, + OPT_PCS_FUNC_ADDRMAP, off); if (opt_dram_map[node].base & OPT_DRAMBASE_MASK_INTRLVEN) lgrp_plat_mem_intrlv++; off += 4; /* limit register offset */ - outl(PCI_CONFADD, PCI_CADDR1(bus, dev, OPT_PCS_FUNC_ADDRMAP, - off)); - opt_dram_map[node].limit = inl(PCI_CONFDATA); + opt_dram_map[node].limit = pci_getl_func(bus, dev, + OPT_PCS_FUNC_ADDRMAP, off); /* * Increment device number to next node and register offset for
--- a/usr/src/uts/i86pc/os/mp_startup.c Wed Nov 16 17:14:14 2005 -0800 +++ b/usr/src/uts/i86pc/os/mp_startup.c Wed Nov 16 18:13:48 2005 -0800 @@ -63,6 +63,7 @@ #include <sys/kdi.h> #include <vm/hat_i86.h> #include <sys/memnode.h> +#include <sys/pci_cfgspace.h> struct cpu cpus[1]; /* CPU data */ struct cpu *cpu[NCPU] = {&cpus[0]}; /* pointers to all CPUs */ @@ -503,6 +504,12 @@ * pessimal set of workarounds needed to cope with *any* of the CPUs in the * system. * + * workaround_errata is invoked early in mlsetup() for CPU 0, and in + * mp_startup() for all slave CPUs. Slaves process workaround_errata prior + * to acknowledging their readiness to the master, so this routine will + * never be executed by multiple CPUs in parallel, thus making updates to + * global data safe. + * * These workarounds are based on Rev 3.57 of the Revision Guide for * AMD Athlon(tm) 64 and AMD Opteron(tm) Processors, August 2005. */ @@ -539,6 +546,11 @@ int opteron_erratum_131; /* if non-zero -> at least one cpu has it */ #endif +#if defined(OPTERON_WORKAROUND_6336786) +int opteron_workaround_6336786; /* non-zero -> WA relevant and applied */ +int opteron_workaround_6336786_UP = 0; /* Not needed for UP */ +#endif + #define WARNING(cpu, n) \ cmn_err(CE_WARN, "cpu%d: no workaround for erratum %d", \ (cpu)->cpu_id, (n)) @@ -775,8 +787,40 @@ if (!(rdmsr(MSR_AMD_NB_CFG) & AMD_NB_CFG_SRQ_HEARTBEAT)) opteron_erratum_131++; } + } #endif + +#if defined(OPTERON_WORKAROUND_6336786) + /* + * This isn't really erratum, but for convenience the + * detection/workaround code lives here and in cpuid_opteron_erratum. + */ + if (cpuid_opteron_erratum(cpu, 6336786) > 0) { + int node; + uint8_t data; + + /* + * Disable C1-Clock ramping on multi-core/multi-processor + * K8 platforms to guard against TSC drift. + */ + if (opteron_workaround_6336786) { + opteron_workaround_6336786++; + } else if ((lgrp_plat_node_cnt * + cpuid_get_ncpu_per_chip(cpu) >= 2) || + opteron_workaround_6336786_UP) { + for (node = 0; node < lgrp_plat_node_cnt; node++) { + /* + * Clear PMM7[1:0] (function 3, offset 0x87) + * Northbridge device is the node id + 24. + */ + data = pci_getb_func(0, node + 24, 3, 0x87); + data &= 0xFC; + pci_putb_func(0, node + 24, 3, 0x87, data); + } + opteron_workaround_6336786++; + } } +#endif return (missing); }