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@amd.com>
Signed-off-by: Hans Rosenfeld <hands.rosenfeld@amd.com>
Acked-by: Jan Beulich <jbeulich@novell.com>
This commit is contained in:
Keir Fraser committed 2010-07-02 19:04:57 +01:00
1 parent 2156299cf0
commit 2604adda4f
5 files changed
+93 -5

No files matched your search

+49 -1
View File
@@ -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
@@ -147,6 +147,54 @@ static void __devinit set_cpuidmask(const struct cpuinfo_x86 *c)
}
}
/*
* 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;
}
/*
* amd_flush_filter={on,off}. Forcibly Enable or disable the TLB flush
* filter on AMD 64-bit processors.
+2 -2
View File
@@ -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);
+3 -2
View File
@@ -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 @@ static void svm_init_erratum_383(struct cpuinfo_x86 *c)
{
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 */
@@ -100,4 +100,39 @@
__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__ */
+4
View File
@@ -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
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.