diff options
author | Keith M Wesolowski <wesolows@foobazco.org> | 2013-12-28 00:25:24 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2014-03-23 20:02:00 -0700 |
commit | 4948216cdd0ccee7b9a4fd433ccab571afbb99e9 (patch) | |
tree | 46336a425aab01021fbc4cbc844d47b4bc808eb1 | |
parent | 56b8f71e3a910fbd2820f6841b40bfd85f9673c2 (diff) | |
download | illumos-joyent-4948216cdd0ccee7b9a4fd433ccab571afbb99e9.tar.gz |
4679 want workaround for Intel erratum BT81
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Approved by: Dan McDonald <danmcd@omniti.com>
-rw-r--r-- | usr/src/uts/i86pc/os/mlsetup.c | 22 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/mp_startup.c | 17 |
2 files changed, 35 insertions, 4 deletions
diff --git a/usr/src/uts/i86pc/os/mlsetup.c b/usr/src/uts/i86pc/os/mlsetup.c index 351ed3d2c9..a653d0d001 100644 --- a/usr/src/uts/i86pc/os/mlsetup.c +++ b/usr/src/uts/i86pc/os/mlsetup.c @@ -199,6 +199,28 @@ mlsetup(struct regs *rp) xen_hvm_init(); /* + * Before we do anything with the TSCs, we need to work around + * Intel erratum BT81. On some CPUs, warm reset does not + * clear the TSC. If we are on such a CPU, we will clear TSC ourselves + * here. Other CPUs will clear it when we boot them later, and the + * resulting skew will be handled by tsc_sync_master()/_slave(); + * note that such skew already exists and has to be handled anyway. + * + * We do this only on metal. This same problem can occur with a + * hypervisor that does not happen to virtualise a TSC that starts from + * zero, regardless of CPU type; however, we do not expect hypervisors + * that do not virtualise TSC that way to handle writes to TSC + * correctly, either. + */ + if (get_hwenv() == HW_NATIVE && + cpuid_getvendor(CPU) == X86_VENDOR_Intel && + cpuid_getfamily(CPU) == 6 && + (cpuid_getmodel(CPU) == 0x2d || cpuid_getmodel(CPU) == 0x3e) && + is_x86_feature(x86_featureset, X86FSET_TSC)) { + (void) wrmsr(REG_TSC, 0UL); + } + + /* * Patch the tsc_read routine with appropriate set of instructions, * depending on the processor family and architecure, to read the * time-stamp counter while ensuring no out-of-order execution. diff --git a/usr/src/uts/i86pc/os/mp_startup.c b/usr/src/uts/i86pc/os/mp_startup.c index c6e8e4b229..61dca9126c 100644 --- a/usr/src/uts/i86pc/os/mp_startup.c +++ b/usr/src/uts/i86pc/os/mp_startup.c @@ -1641,8 +1641,20 @@ mp_startup_common(boolean_t boot) * We need to get TSC on this proc synced (i.e., any delta * from cpu0 accounted for) as soon as we can, because many * many things use gethrtime/pc_gethrestime, including - * interrupts, cmn_err, etc. + * interrupts, cmn_err, etc. Before we can do that, we want to + * clear TSC if we're on a buggy Sandy/Ivy Bridge CPU, so do that + * right away. */ + bzero(new_x86_featureset, BT_SIZEOFMAP(NUM_X86_FEATURES)); + cpuid_pass1(cp, new_x86_featureset); + + if (boot && get_hwenv() == HW_NATIVE && + cpuid_getvendor(CPU) == X86_VENDOR_Intel && + cpuid_getfamily(CPU) == 6 && + (cpuid_getmodel(CPU) == 0x2d || cpuid_getmodel(CPU) == 0x3e) && + is_x86_feature(new_x86_featureset, X86FSET_TSC)) { + (void) wrmsr(REG_TSC, 0UL); + } /* Let the control CPU continue into tsc_sync_master() */ mp_startup_signal(&procset_slave, cp->cpu_id); @@ -1660,9 +1672,6 @@ mp_startup_common(boolean_t boot) */ (void) (*ap_mlsetup)(); - bzero(new_x86_featureset, BT_SIZEOFMAP(NUM_X86_FEATURES)); - cpuid_pass1(cp, new_x86_featureset); - #ifndef __xpv /* * Program this cpu's PAT |