summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Cosgrove <tom@cvs.openbsd.org>2007-02-17 17:38:38 +0000
committerTom Cosgrove <tom@cvs.openbsd.org>2007-02-17 17:38:38 +0000
commit574a3af15cc4802db79e1bab0f6fb86a1be67e35 (patch)
tree55bd86325bdab61acaca8a8c7129b3e8203b8f4b
parentbedcf8741a00e4ceebdf990d943f1d85c88ce422 (diff)
Bring in the AMD errata checks from amd64.
Changes to either copy of amd64errata.c must be replicated in the other. ok deraadt@
-rw-r--r--sys/arch/i386/conf/files.i3863
-rw-r--r--sys/arch/i386/i386/amd64errata.c381
-rw-r--r--sys/arch/i386/i386/machdep.c5
-rw-r--r--sys/arch/i386/include/cpufunc.h32
-rw-r--r--sys/arch/i386/include/specialreg.h47
5 files changed, 464 insertions, 4 deletions
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386
index 0cfb5232e65..e0c62190346 100644
--- a/sys/arch/i386/conf/files.i386
+++ b/sys/arch/i386/conf/files.i386
@@ -1,4 +1,4 @@
-# $OpenBSD: files.i386,v 1.152 2006/11/27 18:04:28 gwk Exp $
+# $OpenBSD: files.i386,v 1.153 2007/02/17 17:38:37 tom Exp $
#
# new style config file for i386 architecture
#
@@ -24,6 +24,7 @@ file arch/i386/i386/in_cksum.s inet
file arch/i386/i386/ipx_cksum.c ipx
file arch/i386/i386/machdep.c
file arch/i386/i386/via.c i686_cpu
+file arch/i386/i386/amd64errata.c i686_cpu
file arch/i386/i386/kgdb_machdep.c kgdb
file arch/i386/i386/longrun.c !small_kernel & i586_cpu
file arch/i386/i386/mem.c
diff --git a/sys/arch/i386/i386/amd64errata.c b/sys/arch/i386/i386/amd64errata.c
new file mode 100644
index 00000000000..70310301122
--- /dev/null
+++ b/sys/arch/i386/i386/amd64errata.c
@@ -0,0 +1,381 @@
+/* $OpenBSD: amd64errata.c,v 1.1 2007/02/17 17:38:37 tom Exp $ */
+/* $NetBSD: errata.c,v 1.6 2007/02/05 21:05:45 ad Exp $ */
+
+/*-
+ * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andrew Doran.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Detect, report on, and work around known errata with AMD amd64 CPUs.
+ *
+ * This is generalised because there are quite a few problems that the
+ * BIOS can patch via MSR, but it is not known if the OS can patch these
+ * yet. The list is expected to grow over time.
+ *
+ * The data here are from: Revision Guide for AMD Athlon 64 and
+ * AMD Opteron Processors, Publication #25759, Revision: 3.69,
+ * Issue Date: September 2006
+ */
+
+#include <sys/param.h>
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/specialreg.h>
+
+
+typedef struct errata {
+ u_short e_num;
+ u_short e_reported;
+ u_int e_data1;
+ const uint8_t *e_set;
+ int (*e_act)(struct cpu_info *, struct errata *);
+ uint64_t e_data2;
+} errata_t;
+
+typedef enum cpurev {
+ BH_E4, CH_CG, CH_D0, DH_CG, DH_D0, DH_E3, DH_E6, JH_E1,
+ JH_E6, SH_B0, SH_B3, SH_C0, SH_CG, SH_D0, SH_E4, SH_E5,
+ OINK
+} cpurev_t;
+
+static const u_int cpurevs[] = {
+ BH_E4, 0x0020fb1, CH_CG, 0x0000f82, CH_CG, 0x0000fb2,
+ CH_D0, 0x0010f80, CH_D0, 0x0010fb0, DH_CG, 0x0000fc0,
+ DH_CG, 0x0000fe0, DH_CG, 0x0000ff0, DH_D0, 0x0010fc0,
+ DH_D0, 0x0010ff0, DH_E3, 0x0020fc0, DH_E3, 0x0020ff0,
+ DH_E6, 0x0020fc2, DH_E6, 0x0020ff2, JH_E1, 0x0020f10,
+ JH_E6, 0x0020f12, JH_E6, 0x0020f32, SH_B0, 0x0000f40,
+ SH_B3, 0x0000f51, SH_C0, 0x0000f48, SH_C0, 0x0000f58,
+ SH_CG, 0x0000f4a, SH_CG, 0x0000f5a, SH_CG, 0x0000f7a,
+ SH_D0, 0x0010f40, SH_D0, 0x0010f50, SH_D0, 0x0010f70,
+ SH_E4, 0x0020f51, SH_E4, 0x0020f71, SH_E5, 0x0020f42,
+ OINK
+};
+
+static const uint8_t amd64_errata_set1[] = {
+ SH_B3, SH_C0, SH_CG, DH_CG, CH_CG, OINK
+};
+
+static const uint8_t amd64_errata_set2[] = {
+ SH_B3, SH_C0, SH_CG, DH_CG, CH_CG, SH_D0, DH_D0, CH_D0, OINK
+};
+
+static const uint8_t amd64_errata_set3[] = {
+ JH_E1, DH_E3, OINK
+};
+
+static const uint8_t amd64_errata_set4[] = {
+ SH_C0, SH_CG, DH_CG, CH_CG, SH_D0, DH_D0, CH_D0, JH_E1,
+ DH_E3, SH_E4, BH_E4, SH_E5, DH_E6, JH_E6, OINK
+};
+
+static const uint8_t amd64_errata_set5[] = {
+ SH_B3, OINK
+};
+
+static const uint8_t amd64_errata_set6[] = {
+ SH_C0, SH_CG, DH_CG, CH_CG, OINK
+};
+
+static const uint8_t amd64_errata_set7[] = {
+ SH_C0, SH_CG, DH_CG, CH_CG, SH_D0, DH_D0, CH_D0, OINK
+};
+
+static const uint8_t amd64_errata_set8[] = {
+ BH_E4, CH_CG, CH_CG, CH_D0, CH_D0, DH_CG, DH_CG, DH_CG,
+ DH_D0, DH_D0, DH_E3, DH_E3, DH_E6, DH_E6, JH_E1, JH_E6,
+ JH_E6, SH_B0, SH_B3, SH_C0, SH_C0, SH_CG, SH_CG, SH_CG,
+ SH_D0, SH_D0, SH_D0, SH_E4, SH_E4, SH_E5, OINK
+};
+
+static int amd64_errata_setmsr(struct cpu_info *, errata_t *);
+static int amd64_errata_testmsr(struct cpu_info *, errata_t *);
+
+static errata_t errata[] = {
+ /*
+ * 81: Cache Coherency Problem with Hardware Prefetching
+ * and Streaming Stores
+ */
+ {
+ 81, 0, MSR_DC_CFG, amd64_errata_set5,
+ amd64_errata_testmsr, DC_CFG_DIS_SMC_CHK_BUF
+ },
+ /*
+ * 86: DRAM Data Masking Feature Can Cause ECC Failures
+ */
+ {
+ 86, 0, MSR_NB_CFG, amd64_errata_set1,
+ amd64_errata_testmsr, NB_CFG_DISDATMSK
+ },
+ /*
+ * 89: Potential Deadlock With Locked Transactions
+ */
+ {
+ 89, 0, MSR_NB_CFG, amd64_errata_set8,
+ amd64_errata_testmsr, NB_CFG_DISIOREQLOCK
+ },
+ /*
+ * 94: Sequential Prefetch Feature May Cause Incorrect
+ * Processor Operation
+ */
+ {
+ 94, 0, MSR_IC_CFG, amd64_errata_set1,
+ amd64_errata_testmsr, IC_CFG_DIS_SEQ_PREFETCH
+ },
+ /*
+ * 97: 128-Bit Streaming Stores May Cause Coherency
+ * Failure
+ *
+ * XXX "This workaround must not be applied to processors
+ * prior to revision C0." We don't apply it, but if it
+ * can't be applied, it shouldn't be reported.
+ */
+ {
+ 97, 0, MSR_DC_CFG, amd64_errata_set6,
+ amd64_errata_testmsr, DC_CFG_DIS_CNV_WC_SSO
+ },
+ /*
+ * 104: DRAM Data Masking Feature Causes ChipKill ECC
+ * Failures When Enabled With x8/x16 DRAM Devices
+ */
+ {
+ 104, 0, MSR_NB_CFG, amd64_errata_set7,
+ amd64_errata_testmsr, NB_CFG_DISDATMSK
+ },
+ /*
+ * 113: Enhanced Write-Combining Feature Causes System Hang
+ */
+ {
+ 113, 0, MSR_BU_CFG, amd64_errata_set3,
+ amd64_errata_setmsr, BU_CFG_WBENHWSBDIS
+ },
+#ifdef MULTIPROCESSOR
+ /*
+ * 69: Multiprocessor Coherency Problem with Hardware
+ * Prefetch Mechanism
+ */
+ {
+ 69, 0, MSR_BU_CFG, amd64_errata_set5,
+ amd64_errata_setmsr, BU_CFG_WBPFSMCCHKDIS
+ },
+ /*
+ * 101: DRAM Scrubber May Cause Data Corruption When Using
+ * Node-Interleaved Memory
+ */
+ {
+ 101, 0, 0, amd64_errata_set2,
+ NULL, 0
+ },
+ /*
+ * 106: Potential Deadlock with Tightly Coupled Semaphores
+ * in an MP System
+ */
+ {
+ 106, 0, MSR_LS_CFG, amd64_errata_set2,
+ amd64_errata_testmsr, LS_CFG_DIS_LS2_SQUISH
+ },
+ /*
+ * 107: Possible Multiprocessor Coherency Problem with
+ * Setting Page Table A/D Bits
+ */
+ {
+ 107, 0, MSR_BU_CFG, amd64_errata_set2,
+ amd64_errata_testmsr, BU_CFG_THRL2IDXCMPDIS
+ },
+#if 0
+ /*
+ * 122: TLB Flush Filter May Cause Coherency Problem in
+ * Multiprocessor Systems
+ */
+ {
+ 122, 0, MSR_HWCR, amd64_errata_set4,
+ amd64_errata_setmsr, HWCR_FFDIS
+ },
+#endif
+#endif /* MULTIPROCESSOR */
+};
+
+static int
+amd64_errata_testmsr(struct cpu_info *ci, errata_t *e)
+{
+ uint64_t val;
+
+ (void)ci;
+
+ val = rdmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE);
+ if ((val & e->e_data2) != 0)
+ return 0; /* not found */
+
+ e->e_reported = 1;
+ return 1; /* found */
+}
+
+static int
+amd64_errata_setmsr(struct cpu_info *ci, errata_t *e)
+{
+ uint64_t val;
+
+ (void)ci;
+
+ val = rdmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE);
+ if ((val & e->e_data2) != 0)
+ return 0; /* not found */
+
+ wrmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE, val | e->e_data2);
+
+#ifdef ERRATA_DEBUG
+ printf("ERRATA: writing a fix\n");
+ val = rdmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE);
+ if ((val & e->e_data2) != 0)
+ printf("ERRATA: fix seems to have worked!\n");
+#endif
+
+ e->e_reported = 1;
+ return 2; /* found and fixed */
+}
+
+void
+amd64_errata(struct cpu_info *ci)
+{
+ errata_t *e, *ex;
+ cpurev_t rev;
+ int i, j;
+ int rc;
+ int found = 0;
+ int corrected = 0;
+ u_int32_t regs[4];
+
+ cpuid(0x80000001, regs);
+
+ for (i = 0; ; i += 2) {
+ if ((rev = cpurevs[i]) == OINK) {
+#ifdef ERRATA_DEBUG
+ printf("ERRATA: this CPU ok\n");
+#endif
+ return;
+ }
+ if (cpurevs[i + 1] == regs[0]) {
+#ifdef ERRATA_DEBUG
+ printf("ERRATA: this CPU has errata\n");
+#endif
+ break;
+ }
+ }
+
+ ex = errata + sizeof(errata) / sizeof(errata[0]);
+
+ /* Reset e_reporteds (for multiple CPUs) */
+ for (e = errata; e < ex; e++)
+ e->e_reported = 0;
+
+ for (e = errata; e < ex; e++) {
+ if (e->e_reported)
+ continue;
+ if (e->e_set != NULL) {
+ for (j = 0; e->e_set[j] != OINK; j++)
+ if (e->e_set[j] == rev)
+ break;
+ if (e->e_set[j] == OINK)
+ continue;
+ }
+
+#ifdef ERRATA_DEBUG
+ printf("%s: testing for erratum %d\n",
+ ci->ci_dev.dv_xname, e->e_num);
+#endif
+
+ /*
+ * If we have an action routine, call it, otherwise
+ * the default is that this erratum is present.
+ */
+ rc = (e->e_act == NULL) ? 1 : (*e->e_act)(ci, e);
+
+ if (rc == 0) /* not found */
+ continue;
+ if (rc == 1)
+ found++;
+ if (rc == 2)
+ corrected++;
+
+ e->e_reported = rc;
+
+#ifdef ERRATA_DEBUG
+ printf("%s: erratum %d present%s\n",
+ ci->ci_dev.dv_xname, e->e_num,
+ (rc == 2) ? " and patched" : "");
+#endif
+ }
+
+#define ERRATA_VERBOSE
+#ifdef ERRATA_VERBOSE
+ if (corrected) {
+ int first = 1;
+
+ /* Print out found and corrected */
+ printf("%s: AMD %s", ci->ci_dev.dv_xname,
+ (corrected == 1) ? "erratum" : "errata");
+ for (e = errata; e < ex; e++) {
+ if (e->e_reported == 2) {
+ if (! first)
+ printf(",");
+ printf(" %d", e->e_num);
+ first = 0;
+ }
+ }
+ printf(" detected and fixed\n");
+ }
+#endif
+
+ if (found) {
+ int first = 1;
+
+ /* Print out found but not corrected */
+ printf("%s: AMD %s", ci->ci_dev.dv_xname,
+ (found == 1) ? "erratum" : "errata");
+ for (e = errata; e < ex; e++) {
+ if (e->e_reported == 1) {
+ if (! first)
+ printf(",");
+ printf(" %d", e->e_num);
+ first = 0;
+ }
+ }
+ printf(" present, BIOS upgrade may be required\n");
+ }
+}
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index da1fb1ab044..838e9e45ce0 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.375 2007/02/13 00:22:48 jsg Exp $ */
+/* $OpenBSD: machdep.c,v 1.376 2007/02/17 17:38:37 tom Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
@@ -1952,6 +1952,9 @@ identifycpu(struct cpu_info *ci)
}
} else
i386_use_fxsave = 0;
+
+ if (vendor == CPUVENDOR_AMD)
+ amd64_errata(ci);
#endif /* I686_CPU */
}
diff --git a/sys/arch/i386/include/cpufunc.h b/sys/arch/i386/include/cpufunc.h
index 832e4271142..0a4134b9462 100644
--- a/sys/arch/i386/include/cpufunc.h
+++ b/sys/arch/i386/include/cpufunc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpufunc.h,v 1.12 2004/06/13 21:49:16 niklas Exp $ */
+/* $OpenBSD: cpufunc.h,v 1.13 2007/02/17 17:38:37 tom Exp $ */
/* $NetBSD: cpufunc.h,v 1.8 1994/10/27 04:15:59 cgd Exp $ */
/*
@@ -238,6 +238,32 @@ rdmsr(u_int msr)
return (rv);
}
+/*
+ * Some of the undocumented AMD64 MSRs need a 'passcode' to access.
+ *
+ * See LinuxBIOSv2: src/cpu/amd/model_fxx/model_fxx_init.c
+ */
+
+#define OPTERON_MSR_PASSCODE 0x9c5a203a
+
+static __inline u_int64_t
+rdmsr_locked(u_int msr, u_int code)
+{
+ uint64_t rv;
+ __asm volatile("rdmsr"
+ : "=A" (rv)
+ : "c" (msr), "D" (code));
+ return (rv);
+}
+
+static __inline void
+wrmsr_locked(u_int msr, u_int code, u_int64_t newval)
+{
+ __asm volatile("wrmsr"
+ :
+ : "A" (newval), "c" (msr), "D" (code));
+}
+
/* Break into DDB/KGDB. */
static __inline void
breakpoint(void)
@@ -245,5 +271,9 @@ breakpoint(void)
__asm __volatile("int $3");
}
+#ifdef I686_CPU
+void amd64_errata(struct cpu_info *);
+#endif
+
#endif /* _KERNEL */
#endif /* !_I386_CPUFUNC_H_ */
diff --git a/sys/arch/i386/include/specialreg.h b/sys/arch/i386/include/specialreg.h
index 91a33c214fa..cc64e01a069 100644
--- a/sys/arch/i386/include/specialreg.h
+++ b/sys/arch/i386/include/specialreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: specialreg.h,v 1.29 2007/02/13 00:22:48 jsg Exp $ */
+/* $OpenBSD: specialreg.h,v 1.30 2007/02/17 17:38:37 tom Exp $ */
/* $NetBSD: specialreg.h,v 1.7 1994/10/27 04:16:26 cgd Exp $ */
/*-
@@ -243,6 +243,51 @@
#define MSR_K6_EPMR 0xc0000086
/*
+ * AMD K8 (Opteron) MSRs.
+ */
+#define MSR_SYSCFG 0xc0000010
+
+#define MSR_EFER 0xc0000080 /* Extended feature enable */
+#define EFER_SCE 0x00000001 /* SYSCALL extension */
+#define EFER_LME 0x00000100 /* Long Mode Active */
+#define EFER_LMA 0x00000400 /* Long Mode Enabled */
+#define EFER_NXE 0x00000800 /* No-Execute Enabled */
+
+#define MSR_STAR 0xc0000081 /* 32 bit syscall gate addr */
+#define MSR_LSTAR 0xc0000082 /* 64 bit syscall gate addr */
+#define MSR_CSTAR 0xc0000083 /* compat syscall gate addr */
+#define MSR_SFMASK 0xc0000084 /* flags to clear on syscall */
+
+#define MSR_FSBASE 0xc0000100 /* 64bit offset for fs: */
+#define MSR_GSBASE 0xc0000101 /* 64bit offset for gs: */
+#define MSR_KERNELGSBASE 0xc0000102 /* storage for swapgs ins */
+
+/*
+ * These require a 'passcode' for access. See cpufunc.h.
+ */
+#define MSR_HWCR 0xc0010015
+#define HWCR_FFDIS 0x00000040
+
+#define MSR_NB_CFG 0xc001001f
+#define NB_CFG_DISIOREQLOCK 0x0000000000000004ULL
+#define NB_CFG_DISDATMSK 0x0000001000000000ULL
+
+#define MSR_LS_CFG 0xc0011020
+#define LS_CFG_DIS_LS2_SQUISH 0x02000000
+
+#define MSR_IC_CFG 0xc0011021
+#define IC_CFG_DIS_SEQ_PREFETCH 0x00000800
+
+#define MSR_DC_CFG 0xc0011022
+#define DC_CFG_DIS_CNV_WC_SSO 0x00000004
+#define DC_CFG_DIS_SMC_CHK_BUF 0x00000400
+
+#define MSR_BU_CFG 0xc0011023
+#define BU_CFG_THRL2IDXCMPDIS 0x0000080000000000ULL
+#define BU_CFG_WBPFSMCCHKDIS 0x0000200000000000ULL
+#define BU_CFG_WBENHWSBDIS 0x0001000000000000ULL
+
+/*
* Constants related to MTRRs
*/
#define MTRR_N64K 8 /* numbers of fixed-size entries */