[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] AMD OSVW (OS Visible Workaround) for Xen
This path enables AMD OSVW (OS Visible Workaround) feature for Xen. New AMD errata will have a OSVW id assigned in the future. OS is supposed to check OSVW status MSR to find out whether CPU has a specific erratum. Legacy errata are also supported in this patch: traditional family/model/stepping approach will be used if OSVW feature isn't applicable. This patch is adapted from Hans Rosenfeld's patch submitted to Linux kernel . Signed-off-by: Wei Huang <wei.huang2@xxxxxxx> Signed-off-by: Hans Rosenfeld <hands.rosenfeld@xxxxxxx> Acked-by: Jan Beulich <jbeulich@xxxxxxxxxx> diff -r aecf092da748 xen/arch/x86/cpu/amd.c --- a/xen/arch/x86/cpu/amd.c Wed Jun 30 22:12:54 2010 +0100 +++ b/xen/arch/x86/cpu/amd.c Thu Jul 01 14:01:45 2010 -0500 @@ -7,12 +7,12 @@ #include <asm/io.h> #include <asm/msr.h> #include <asm/processor.h> +#include <asm/amd.h> #include <asm/hvm/support.h> #include <asm/setup.h> /* amd_init_cpu */ #include <asm/acpi.h> #include "cpu.h" -#include "amd.h" /* * Pre-canned values for overriding the CPUID features @@ -145,6 +145,54 @@ wrmsr_amd(MSR_K8_FEATURE_MASK, feat_edx, feat_ecx); wrmsr_amd(MSR_K8_EXT_FEATURE_MASK, extfeat_edx, extfeat_ecx); } +} + +/* + * Check for the presence of an AMD erratum. Arguments are defined in amd.h + * for each known erratum. Return 1 if erratum is found. + */ +int cpu_has_amd_erratum(const struct cpuinfo_x86 *cpu, int osvw, ...) +{ + va_list ap; + u32 range; + u32 ms; + + if (cpu->x86_vendor != X86_VENDOR_AMD) + return 0; + + va_start(ap, osvw); + + if (osvw) { + u16 osvw_id = va_arg(ap, int); + + if (cpu_has(cpu, X86_FEATURE_OSVW)) { + u64 osvw_len; + rdmsrl(MSR_AMD_OSVW_ID_LENGTH, osvw_len); + + if (osvw_id < osvw_len) { + u64 osvw_bits; + rdmsrl(MSR_AMD_OSVW_STATUS + (osvw_id >> 6), + osvw_bits); + + va_end(ap); + return (osvw_bits >> (osvw_id & 0x3f)) & 0x01; + } + } + } + + /* OSVW unavailable or ID unknown, match family-model-stepping range */ + ms = (cpu->x86_model << 8) | cpu->x86_mask; + while ((range = va_arg(ap, int))) { + if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) && + (ms >= AMD_MODEL_RANGE_START(range)) && + (ms <= AMD_MODEL_RANGE_END(range))) { + va_end(ap); + return 1; + } + } + + va_end(ap); + return 0; } /* diff -r aecf092da748 xen/arch/x86/cpu/amd.h --- a/xen/arch/x86/cpu/amd.h Wed Jun 30 22:12:54 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/* - * amd.h - AMD processor specific definitions - */ - -#ifndef __AMD_H__ -#define __AMD_H__ - -#include <asm/cpufeature.h> - -/* CPUID masked for use by AMD-V Extended Migration */ - -#define X86_FEATURE_BITPOS(_feature_) ((_feature_) % 32) -#define __bit(_x_) (1U << X86_FEATURE_BITPOS(_x_)) - -/* Family 0Fh, Revision C */ -#define AMD_FEATURES_K8_REV_C_ECX 0 -#define AMD_FEATURES_K8_REV_C_EDX ( \ - __bit(X86_FEATURE_FPU) | __bit(X86_FEATURE_VME) | \ - __bit(X86_FEATURE_DE) | __bit(X86_FEATURE_PSE) | \ - __bit(X86_FEATURE_TSC) | __bit(X86_FEATURE_MSR) | \ - __bit(X86_FEATURE_PAE) | __bit(X86_FEATURE_MCE) | \ - __bit(X86_FEATURE_CX8) | __bit(X86_FEATURE_APIC) | \ - __bit(X86_FEATURE_SEP) | __bit(X86_FEATURE_MTRR) | \ - __bit(X86_FEATURE_PGE) | __bit(X86_FEATURE_MCA) | \ - __bit(X86_FEATURE_CMOV) | __bit(X86_FEATURE_PAT) | \ - __bit(X86_FEATURE_PSE36) | __bit(X86_FEATURE_CLFLSH)| \ - __bit(X86_FEATURE_MMX) | __bit(X86_FEATURE_FXSR) | \ - __bit(X86_FEATURE_XMM) | __bit(X86_FEATURE_XMM2)) -#define AMD_EXTFEATURES_K8_REV_C_ECX 0 -#define AMD_EXTFEATURES_K8_REV_C_EDX ( \ - __bit(X86_FEATURE_FPU) | __bit(X86_FEATURE_VME) | \ - __bit(X86_FEATURE_DE) | __bit(X86_FEATURE_PSE) | \ - __bit(X86_FEATURE_TSC) | __bit(X86_FEATURE_MSR) | \ - __bit(X86_FEATURE_PAE) | __bit(X86_FEATURE_MCE) | \ - __bit(X86_FEATURE_CX8) | __bit(X86_FEATURE_APIC) | \ - __bit(X86_FEATURE_SYSCALL) | __bit(X86_FEATURE_MTRR) | \ - __bit(X86_FEATURE_PGE) | __bit(X86_FEATURE_MCA) | \ - __bit(X86_FEATURE_CMOV) | __bit(X86_FEATURE_PAT) | \ - __bit(X86_FEATURE_PSE36) | __bit(X86_FEATURE_NX) | \ - __bit(X86_FEATURE_MMXEXT) | __bit(X86_FEATURE_MMX) | \ - __bit(X86_FEATURE_FXSR) | __bit(X86_FEATURE_LM) | \ - __bit(X86_FEATURE_3DNOWEXT) | __bit(X86_FEATURE_3DNOW)) - -/* Family 0Fh, Revision D */ -#define AMD_FEATURES_K8_REV_D_ECX AMD_FEATURES_K8_REV_C_ECX -#define AMD_FEATURES_K8_REV_D_EDX AMD_FEATURES_K8_REV_C_EDX -#define AMD_EXTFEATURES_K8_REV_D_ECX (AMD_EXTFEATURES_K8_REV_C_ECX |\ - __bit(X86_FEATURE_LAHF_LM)) -#define AMD_EXTFEATURES_K8_REV_D_EDX (AMD_EXTFEATURES_K8_REV_C_EDX |\ - __bit(X86_FEATURE_FFXSR)) - -/* Family 0Fh, Revision E */ -#define AMD_FEATURES_K8_REV_E_ECX (AMD_FEATURES_K8_REV_D_ECX | \ - __bit(X86_FEATURE_XMM3)) -#define AMD_FEATURES_K8_REV_E_EDX (AMD_FEATURES_K8_REV_D_EDX | \ - __bit(X86_FEATURE_HT)) -#define AMD_EXTFEATURES_K8_REV_E_ECX (AMD_EXTFEATURES_K8_REV_D_ECX |\ - __bit(X86_FEATURE_CMP_LEGACY)) -#define AMD_EXTFEATURES_K8_REV_E_EDX AMD_EXTFEATURES_K8_REV_D_EDX - -/* Family 0Fh, Revision F */ -#define AMD_FEATURES_K8_REV_F_ECX (AMD_FEATURES_K8_REV_E_ECX | \ - __bit(X86_FEATURE_CX16)) -#define AMD_FEATURES_K8_REV_F_EDX AMD_FEATURES_K8_REV_E_EDX -#define AMD_EXTFEATURES_K8_REV_F_ECX (AMD_EXTFEATURES_K8_REV_E_ECX |\ - __bit(X86_FEATURE_SVME) | __bit(X86_FEATURE_EXTAPICSPACE) | \ - __bit(X86_FEATURE_ALTMOVCR)) -#define AMD_EXTFEATURES_K8_REV_F_EDX (AMD_EXTFEATURES_K8_REV_E_EDX |\ - __bit(X86_FEATURE_RDTSCP)) - -/* Family 0Fh, Revision G */ -#define AMD_FEATURES_K8_REV_G_ECX AMD_FEATURES_K8_REV_F_ECX -#define AMD_FEATURES_K8_REV_G_EDX AMD_FEATURES_K8_REV_F_EDX -#define AMD_EXTFEATURES_K8_REV_G_ECX (AMD_EXTFEATURES_K8_REV_F_ECX |\ - __bit(X86_FEATURE_3DNOWPF)) -#define AMD_EXTFEATURES_K8_REV_G_EDX AMD_EXTFEATURES_K8_REV_F_EDX - -/* Family 10h, Revision B */ -#define AMD_FEATURES_FAM10h_REV_B_ECX (AMD_FEATURES_K8_REV_F_ECX | \ - __bit(X86_FEATURE_POPCNT) | __bit(X86_FEATURE_MWAIT)) -#define AMD_FEATURES_FAM10h_REV_B_EDX AMD_FEATURES_K8_REV_F_EDX -#define AMD_EXTFEATURES_FAM10h_REV_B_ECX (AMD_EXTFEATURES_K8_REV_F_ECX |\ - __bit(X86_FEATURE_ABM) | __bit(X86_FEATURE_SSE4A) | \ - __bit(X86_FEATURE_MISALIGNSSE) | __bit(X86_FEATURE_OSVW) | \ - __bit(X86_FEATURE_IBS)) -#define AMD_EXTFEATURES_FAM10h_REV_B_EDX (AMD_EXTFEATURES_K8_REV_F_EDX |\ - __bit(X86_FEATURE_PAGE1GB)) - -/* Family 10h, Revision C */ -#define AMD_FEATURES_FAM10h_REV_C_ECX AMD_FEATURES_FAM10h_REV_B_ECX -#define AMD_FEATURES_FAM10h_REV_C_EDX AMD_FEATURES_FAM10h_REV_B_EDX -#define AMD_EXTFEATURES_FAM10h_REV_C_ECX (AMD_EXTFEATURES_FAM10h_REV_B_ECX |\ - __bit(X86_FEATURE_SKINIT) | __bit(X86_FEATURE_WDT)) -#define AMD_EXTFEATURES_FAM10h_REV_C_EDX AMD_EXTFEATURES_FAM10h_REV_B_EDX - -/* Family 11h, Revision B */ -#define AMD_FEATURES_FAM11h_REV_B_ECX AMD_FEATURES_K8_REV_G_ECX -#define AMD_FEATURES_FAM11h_REV_B_EDX AMD_FEATURES_K8_REV_G_EDX -#define AMD_EXTFEATURES_FAM11h_REV_B_ECX (AMD_EXTFEATURES_K8_REV_G_ECX |\ - __bit(X86_FEATURE_SKINIT)) -#define AMD_EXTFEATURES_FAM11h_REV_B_EDX AMD_EXTFEATURES_K8_REV_G_EDX - -#endif /* __AMD_H__ */ diff -r aecf092da748 xen/arch/x86/hvm/svm/asid.c --- a/xen/arch/x86/hvm/svm/asid.c Wed Jun 30 22:12:54 2010 +0100 +++ b/xen/arch/x86/hvm/svm/asid.c Thu Jul 01 14:01:45 2010 -0500 @@ -21,14 +21,14 @@ #include <xen/lib.h> #include <xen/perfc.h> #include <asm/hvm/svm/asid.h> +#include <asm/amd.h> void svm_asid_init(struct cpuinfo_x86 *c) { int nasids = 0; /* Check for erratum #170, and leave ASIDs disabled if it's present. */ - if ( (c->x86 == 0x10) || - ((c->x86 == 0xf) && (c->x86_model >= 0x68) && (c->x86_mask >= 1)) ) + if ( !cpu_has_amd_erratum(c, AMD_ERRATUM_170) ) nasids = cpuid_ebx(0x8000000A); hvm_asid_init(nasids); diff -r aecf092da748 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Wed Jun 30 22:12:54 2010 +0100 +++ b/xen/arch/x86/hvm/svm/svm.c Thu Jul 01 14:01:45 2010 -0500 @@ -34,6 +34,7 @@ #include <asm/regs.h> #include <asm/cpufeature.h> #include <asm/processor.h> +#include <asm/amd.h> #include <asm/types.h> #include <asm/debugreg.h> #include <asm/msr.h> @@ -846,8 +847,8 @@ { uint64_t msr_content; - /* only family 10h is affected */ - if ( c->x86 != 0x10 ) + /* check whether CPU is affected */ + if ( !cpu_has_amd_erratum(c, AMD_ERRATUM_383) ) return; /* use safe methods to be compatible with nested virtualization */ diff -r aecf092da748 xen/include/asm-x86/amd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/asm-x86/amd.h Thu Jul 01 14:01:45 2010 -0500 @@ -0,0 +1,138 @@ +/* + * amd.h - AMD processor specific definitions + */ + +#ifndef __AMD_H__ +#define __AMD_H__ + +#include <asm/cpufeature.h> + +/* CPUID masked for use by AMD-V Extended Migration */ + +#define X86_FEATURE_BITPOS(_feature_) ((_feature_) % 32) +#define __bit(_x_) (1U << X86_FEATURE_BITPOS(_x_)) + +/* Family 0Fh, Revision C */ +#define AMD_FEATURES_K8_REV_C_ECX 0 +#define AMD_FEATURES_K8_REV_C_EDX ( \ + __bit(X86_FEATURE_FPU) | __bit(X86_FEATURE_VME) | \ + __bit(X86_FEATURE_DE) | __bit(X86_FEATURE_PSE) | \ + __bit(X86_FEATURE_TSC) | __bit(X86_FEATURE_MSR) | \ + __bit(X86_FEATURE_PAE) | __bit(X86_FEATURE_MCE) | \ + __bit(X86_FEATURE_CX8) | __bit(X86_FEATURE_APIC) | \ + __bit(X86_FEATURE_SEP) | __bit(X86_FEATURE_MTRR) | \ + __bit(X86_FEATURE_PGE) | __bit(X86_FEATURE_MCA) | \ + __bit(X86_FEATURE_CMOV) | __bit(X86_FEATURE_PAT) | \ + __bit(X86_FEATURE_PSE36) | __bit(X86_FEATURE_CLFLSH)| \ + __bit(X86_FEATURE_MMX) | __bit(X86_FEATURE_FXSR) | \ + __bit(X86_FEATURE_XMM) | __bit(X86_FEATURE_XMM2)) +#define AMD_EXTFEATURES_K8_REV_C_ECX 0 +#define AMD_EXTFEATURES_K8_REV_C_EDX ( \ + __bit(X86_FEATURE_FPU) | __bit(X86_FEATURE_VME) | \ + __bit(X86_FEATURE_DE) | __bit(X86_FEATURE_PSE) | \ + __bit(X86_FEATURE_TSC) | __bit(X86_FEATURE_MSR) | \ + __bit(X86_FEATURE_PAE) | __bit(X86_FEATURE_MCE) | \ + __bit(X86_FEATURE_CX8) | __bit(X86_FEATURE_APIC) | \ + __bit(X86_FEATURE_SYSCALL) | __bit(X86_FEATURE_MTRR) | \ + __bit(X86_FEATURE_PGE) | __bit(X86_FEATURE_MCA) | \ + __bit(X86_FEATURE_CMOV) | __bit(X86_FEATURE_PAT) | \ + __bit(X86_FEATURE_PSE36) | __bit(X86_FEATURE_NX) | \ + __bit(X86_FEATURE_MMXEXT) | __bit(X86_FEATURE_MMX) | \ + __bit(X86_FEATURE_FXSR) | __bit(X86_FEATURE_LM) | \ + __bit(X86_FEATURE_3DNOWEXT) | __bit(X86_FEATURE_3DNOW)) + +/* Family 0Fh, Revision D */ +#define AMD_FEATURES_K8_REV_D_ECX AMD_FEATURES_K8_REV_C_ECX +#define AMD_FEATURES_K8_REV_D_EDX AMD_FEATURES_K8_REV_C_EDX +#define AMD_EXTFEATURES_K8_REV_D_ECX (AMD_EXTFEATURES_K8_REV_C_ECX |\ + __bit(X86_FEATURE_LAHF_LM)) +#define AMD_EXTFEATURES_K8_REV_D_EDX (AMD_EXTFEATURES_K8_REV_C_EDX |\ + __bit(X86_FEATURE_FFXSR)) + +/* Family 0Fh, Revision E */ +#define AMD_FEATURES_K8_REV_E_ECX (AMD_FEATURES_K8_REV_D_ECX | \ + __bit(X86_FEATURE_XMM3)) +#define AMD_FEATURES_K8_REV_E_EDX (AMD_FEATURES_K8_REV_D_EDX | \ + __bit(X86_FEATURE_HT)) +#define AMD_EXTFEATURES_K8_REV_E_ECX (AMD_EXTFEATURES_K8_REV_D_ECX |\ + __bit(X86_FEATURE_CMP_LEGACY)) +#define AMD_EXTFEATURES_K8_REV_E_EDX AMD_EXTFEATURES_K8_REV_D_EDX + +/* Family 0Fh, Revision F */ +#define AMD_FEATURES_K8_REV_F_ECX (AMD_FEATURES_K8_REV_E_ECX | \ + __bit(X86_FEATURE_CX16)) +#define AMD_FEATURES_K8_REV_F_EDX AMD_FEATURES_K8_REV_E_EDX +#define AMD_EXTFEATURES_K8_REV_F_ECX (AMD_EXTFEATURES_K8_REV_E_ECX |\ + __bit(X86_FEATURE_SVME) | __bit(X86_FEATURE_EXTAPICSPACE) | \ + __bit(X86_FEATURE_ALTMOVCR)) +#define AMD_EXTFEATURES_K8_REV_F_EDX (AMD_EXTFEATURES_K8_REV_E_EDX |\ + __bit(X86_FEATURE_RDTSCP)) + +/* Family 0Fh, Revision G */ +#define AMD_FEATURES_K8_REV_G_ECX AMD_FEATURES_K8_REV_F_ECX +#define AMD_FEATURES_K8_REV_G_EDX AMD_FEATURES_K8_REV_F_EDX +#define AMD_EXTFEATURES_K8_REV_G_ECX (AMD_EXTFEATURES_K8_REV_F_ECX |\ + __bit(X86_FEATURE_3DNOWPF)) +#define AMD_EXTFEATURES_K8_REV_G_EDX AMD_EXTFEATURES_K8_REV_F_EDX + +/* Family 10h, Revision B */ +#define AMD_FEATURES_FAM10h_REV_B_ECX (AMD_FEATURES_K8_REV_F_ECX | \ + __bit(X86_FEATURE_POPCNT) | __bit(X86_FEATURE_MWAIT)) +#define AMD_FEATURES_FAM10h_REV_B_EDX AMD_FEATURES_K8_REV_F_EDX +#define AMD_EXTFEATURES_FAM10h_REV_B_ECX (AMD_EXTFEATURES_K8_REV_F_ECX |\ + __bit(X86_FEATURE_ABM) | __bit(X86_FEATURE_SSE4A) | \ + __bit(X86_FEATURE_MISALIGNSSE) | __bit(X86_FEATURE_OSVW) | \ + __bit(X86_FEATURE_IBS)) +#define AMD_EXTFEATURES_FAM10h_REV_B_EDX (AMD_EXTFEATURES_K8_REV_F_EDX |\ + __bit(X86_FEATURE_PAGE1GB)) + +/* Family 10h, Revision C */ +#define AMD_FEATURES_FAM10h_REV_C_ECX AMD_FEATURES_FAM10h_REV_B_ECX +#define AMD_FEATURES_FAM10h_REV_C_EDX AMD_FEATURES_FAM10h_REV_B_EDX +#define AMD_EXTFEATURES_FAM10h_REV_C_ECX (AMD_EXTFEATURES_FAM10h_REV_B_ECX |\ + __bit(X86_FEATURE_SKINIT) | __bit(X86_FEATURE_WDT)) +#define AMD_EXTFEATURES_FAM10h_REV_C_EDX AMD_EXTFEATURES_FAM10h_REV_B_EDX + +/* Family 11h, Revision B */ +#define AMD_FEATURES_FAM11h_REV_B_ECX AMD_FEATURES_K8_REV_G_ECX +#define AMD_FEATURES_FAM11h_REV_B_EDX AMD_FEATURES_K8_REV_G_EDX +#define AMD_EXTFEATURES_FAM11h_REV_B_ECX (AMD_EXTFEATURES_K8_REV_G_ECX |\ + __bit(X86_FEATURE_SKINIT)) +#define AMD_EXTFEATURES_FAM11h_REV_B_EDX AMD_EXTFEATURES_K8_REV_G_EDX + +/* AMD errata checking + * + * Errata are defined using the AMD_LEGACY_ERRATUM() or 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(). + * + * Example 1: + * #define AMD_ERRATUM_319 \ + * AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0x4, 0x2), \ + * AMD_MODEL_RANGE(0x10, 0x8, 0x0, 0x8, 0x0), \ + * AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0)) + * Example 2: + * #define AMD_ERRATUM_400 \ + * AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf), \ + * AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf)) + * + */ + +#define AMD_LEGACY_ERRATUM(...) 0 /* legacy */, __VA_ARGS__, 0 +#define AMD_OSVW_ERRATUM(osvw_id, ...) 1 /* osvw */, 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) + +#define AMD_ERRATUM_170 \ + AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x0f, 0x0, 0x0, 0x67, 0xf)) + +#define AMD_ERRATUM_383 \ + AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf), \ + AMD_MODEL_RANGE(0x12, 0x0, 0x0, 0x1, 0x0)) + +int cpu_has_amd_erratum(const struct cpuinfo_x86 *, int, ...); +#endif /* __AMD_H__ */ diff -r aecf092da748 xen/include/asm-x86/msr-index.h --- a/xen/include/asm-x86/msr-index.h Wed Jun 30 22:12:54 2010 +0100 +++ b/xen/include/asm-x86/msr-index.h Thu Jul 01 14:01:45 2010 -0500 @@ -252,6 +252,10 @@ #define MSR_AMD_PATCHLEVEL 0x0000008b #define MSR_AMD_PATCHLOADER 0xc0010020 +/* AMD OS Visible Workaround MSRs */ +#define MSR_AMD_OSVW_ID_LENGTH 0xc0010140 +#define MSR_AMD_OSVW_STATUS 0xc0010141 + /* K6 MSRs */ #define MSR_K6_EFER 0xc0000080 #define MSR_K6_STAR 0xc0000081 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |