|
@@ -20,11 +20,11 @@
|
|
|
|
|
|
static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
|
|
|
{
|
|
|
- struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
|
|
|
u32 gprs[8] = { 0 };
|
|
|
int err;
|
|
|
|
|
|
- WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__);
|
|
|
+ WARN_ONCE((boot_cpu_data.x86 != 0xf),
|
|
|
+ "%s should only be used on K8!\n", __func__);
|
|
|
|
|
|
gprs[1] = msr;
|
|
|
gprs[7] = 0x9c5a203a;
|
|
@@ -38,10 +38,10 @@ static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
|
|
|
|
|
|
static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
|
|
|
{
|
|
|
- struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
|
|
|
u32 gprs[8] = { 0 };
|
|
|
|
|
|
- WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__);
|
|
|
+ WARN_ONCE((boot_cpu_data.x86 != 0xf),
|
|
|
+ "%s should only be used on K8!\n", __func__);
|
|
|
|
|
|
gprs[0] = (u32)val;
|
|
|
gprs[1] = msr;
|
|
@@ -192,11 +192,11 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
|
|
|
/* Athlon 660/661 is valid. */
|
|
|
if ((c->x86_model == 6) && ((c->x86_mask == 0) ||
|
|
|
(c->x86_mask == 1)))
|
|
|
- goto valid_k7;
|
|
|
+ return;
|
|
|
|
|
|
/* Duron 670 is valid */
|
|
|
if ((c->x86_model == 7) && (c->x86_mask == 0))
|
|
|
- goto valid_k7;
|
|
|
+ return;
|
|
|
|
|
|
/*
|
|
|
* Athlon 662, Duron 671, and Athlon >model 7 have capability
|
|
@@ -209,7 +209,7 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
|
|
|
((c->x86_model == 7) && (c->x86_mask >= 1)) ||
|
|
|
(c->x86_model > 7))
|
|
|
if (cpu_has_mp)
|
|
|
- goto valid_k7;
|
|
|
+ return;
|
|
|
|
|
|
/* If we get here, not a certified SMP capable AMD system. */
|
|
|
|
|
@@ -220,9 +220,6 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
|
|
|
WARN_ONCE(1, "WARNING: This combination of AMD"
|
|
|
" processors is not suitable for SMP.\n");
|
|
|
add_taint(TAINT_UNSAFE_SMP, LOCKDEP_NOW_UNRELIABLE);
|
|
|
-
|
|
|
-valid_k7:
|
|
|
- ;
|
|
|
}
|
|
|
|
|
|
static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c)
|
|
@@ -513,6 +510,10 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+static const int amd_erratum_383[];
|
|
|
+static const int amd_erratum_400[];
|
|
|
+static bool cpu_has_amd_erratum(const int *erratum);
|
|
|
+
|
|
|
static void __cpuinit init_amd(struct cpuinfo_x86 *c)
|
|
|
{
|
|
|
u32 dummy;
|
|
@@ -727,8 +728,14 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
|
|
|
rdmsrl_safe(MSR_AMD64_BU_CFG2, &value);
|
|
|
value &= ~(1ULL << 24);
|
|
|
wrmsrl_safe(MSR_AMD64_BU_CFG2, value);
|
|
|
+
|
|
|
+ if (cpu_has_amd_erratum(amd_erratum_383))
|
|
|
+ set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
|
|
|
}
|
|
|
|
|
|
+ if (cpu_has_amd_erratum(amd_erratum_400))
|
|
|
+ set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
|
|
|
+
|
|
|
rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
|
|
|
}
|
|
|
|
|
@@ -847,8 +854,7 @@ cpu_dev_register(amd_cpu_dev);
|
|
|
* AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that
|
|
|
* have an OSVW id assigned, which it takes as first argument. Both take a
|
|
|
* variable number of family-specific model-stepping ranges created by
|
|
|
- * AMD_MODEL_RANGE(). Each erratum also has to be declared as extern const
|
|
|
- * int[] in arch/x86/include/asm/processor.h.
|
|
|
+ * AMD_MODEL_RANGE().
|
|
|
*
|
|
|
* Example:
|
|
|
*
|
|
@@ -858,16 +864,22 @@ cpu_dev_register(amd_cpu_dev);
|
|
|
* AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0));
|
|
|
*/
|
|
|
|
|
|
-const int amd_erratum_400[] =
|
|
|
+#define AMD_LEGACY_ERRATUM(...) { -1, __VA_ARGS__, 0 }
|
|
|
+#define AMD_OSVW_ERRATUM(osvw_id, ...) { osvw_id, __VA_ARGS__, 0 }
|
|
|
+#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \
|
|
|
+ ((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end))
|
|
|
+#define AMD_MODEL_RANGE_FAMILY(range) (((range) >> 24) & 0xff)
|
|
|
+#define AMD_MODEL_RANGE_START(range) (((range) >> 12) & 0xfff)
|
|
|
+#define AMD_MODEL_RANGE_END(range) ((range) & 0xfff)
|
|
|
+
|
|
|
+static const int amd_erratum_400[] =
|
|
|
AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
|
|
|
AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
|
|
|
-EXPORT_SYMBOL_GPL(amd_erratum_400);
|
|
|
|
|
|
-const int amd_erratum_383[] =
|
|
|
+static const int amd_erratum_383[] =
|
|
|
AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
|
|
|
-EXPORT_SYMBOL_GPL(amd_erratum_383);
|
|
|
|
|
|
-bool cpu_has_amd_erratum(const int *erratum)
|
|
|
+static bool cpu_has_amd_erratum(const int *erratum)
|
|
|
{
|
|
|
struct cpuinfo_x86 *cpu = __this_cpu_ptr(&cpu_info);
|
|
|
int osvw_id = *erratum++;
|
|
@@ -908,5 +920,3 @@ bool cpu_has_amd_erratum(const int *erratum)
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
-
|
|
|
-EXPORT_SYMBOL_GPL(cpu_has_amd_erratum);
|