summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith M Wesolowski <wesolows@foobazco.org>2013-12-28 00:25:24 +0000
committerRobert Mustacchi <rm@joyent.com>2014-03-23 20:02:00 -0700
commit4948216cdd0ccee7b9a4fd433ccab571afbb99e9 (patch)
tree46336a425aab01021fbc4cbc844d47b4bc808eb1
parent56b8f71e3a910fbd2820f6841b40bfd85f9673c2 (diff)
downloadillumos-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.c22
-rw-r--r--usr/src/uts/i86pc/os/mp_startup.c17
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