Extended migration support
PATCH 1/1 Extended migration support
This patch adds support for AMD's extended migration, aka CPUID features and extended features masking.
Signed-of-by Travis Betak <[email protected]>
xen/arch/x86/cpu/amd.c +131 -0
@@ -10,8 +10,137 @@#include <asm/hvm/support.h> #include "cpu.h" +#include "amd.h" int start_svm (struct cpuinfo_x86 *c); + +/* +* Pre-canned values for overriding the CPUID features +* and extended features masks. +* +* Currently supported processors: +* +* "fam_0f_rev_c" +* "fam_0f_rev_d" +* "fam_0f_rev_e" +* "fam_0f_rev_f" +* "fam_0f_rev_g" +* "fam_10_rev_b" +* "fam_10_rev_c" +* "fam_11_rev_b" +*/ +static char opt_famrev[14 ]; +string_param ("cpuid_mask_cpu" , opt_famrev); + +/* Finer-grained CPUID feature control. */ +static unsigned int opt_cpuid_mask_ecx, opt_cpuid_mask_edx; +integer_param ("cpuid_mask_ecx" , opt_cpuid_mask_ecx); +integer_param ("cpuid_mask_edx" , opt_cpuid_mask_edx); +static unsigned int opt_cpuid_mask_ext_ecx, opt_cpuid_mask_ext_edx; +integer_param ("cpuid_mask_ecx" , opt_cpuid_mask_ext_ecx); +integer_param ("cpuid_mask_edx" , opt_cpuid_mask_ext_edx); + +static inline void wrmsr_amd (unsigned int index,unsigned int lo, +unsigned int hi) +{ + __asm__ __volatile__ ( +"wrmsr" + :/* No outputs */ + :"c" (index),"a" (lo), +"d" (hi),"D" (0x9c5a203a ) + ); +} + +/* +* Mask the features and extended features returned by CPUID. Parameters are +* set from the boot line via two methods: +* +* 1) Specific processor revision string +* 2) User-defined masks +* +* The processor revision string parameter has precedene. +*/ +static void __devinit set_cpuidmask (struct cpuinfo_x86 *c) +{ +unsigned int feat_ecx, feat_edx; +unsigned int extfeat_ecx, extfeat_edx; + +/* FIXME check if processor supports CPUID masking */ + +/* Check if we were given specific processor to emulate. */ +if (opt_famrev[0 ] !='\0' ) + { +if (!strcmp (opt_famrev,"fam_0f_rev_c" )) { + feat_ecx =AMD_FEATURES_K8_REV_C_ECX ; + feat_edx =AMD_FEATURES_K8_REV_C_EDX ; + extfeat_ecx =AMD_EXTFEATURES_K8_REV_C_ECX ; + extfeat_edx =AMD_EXTFEATURES_K8_REV_C_EDX ; + }else if (!strcmp (opt_famrev,"fam_0f_rev_d" )) { + feat_ecx =AMD_FEATURES_K8_REV_D_ECX ; + feat_edx =AMD_FEATURES_K8_REV_D_EDX ; + extfeat_ecx =AMD_EXTFEATURES_K8_REV_D_ECX ; + extfeat_edx =AMD_EXTFEATURES_K8_REV_D_EDX ; + }else if (!strcmp (opt_famrev,"fam_0f_rev_e" )) { + feat_ecx =AMD_FEATURES_K8_REV_E_ECX ; + feat_edx =AMD_FEATURES_K8_REV_E_EDX ; + extfeat_ecx =AMD_EXTFEATURES_K8_REV_E_ECX ; + extfeat_edx =AMD_EXTFEATURES_K8_REV_E_EDX ; + }else if (!strcmp (opt_famrev,"fam_0f_rev_f" )) { + feat_ecx =AMD_FEATURES_K8_REV_F_ECX ; + feat_edx =AMD_FEATURES_K8_REV_F_EDX ; + extfeat_ecx =AMD_EXTFEATURES_K8_REV_F_ECX ; + extfeat_edx =AMD_EXTFEATURES_K8_REV_F_EDX ; + }else if (!strcmp (opt_famrev,"fam_0f_rev_g" )) { + feat_ecx =AMD_FEATURES_K8_REV_G_ECX ; + feat_edx =AMD_FEATURES_K8_REV_G_EDX ; + extfeat_ecx =AMD_EXTFEATURES_K8_REV_G_ECX ; + extfeat_edx =AMD_EXTFEATURES_K8_REV_G_EDX ; + }else if (!strcmp (opt_famrev,"fam_10_rev_b" )) { + feat_ecx = AMD_FEATURES_FAM10h_REV_B_ECX; + feat_edx = AMD_FEATURES_FAM10h_REV_B_EDX; + extfeat_ecx = AMD_EXTFEATURES_FAM10h_REV_B_ECX; + extfeat_edx = AMD_EXTFEATURES_FAM10h_REV_B_EDX; + }else if (!strcmp (opt_famrev,"fam_10_rev_c" )) { + feat_ecx = AMD_FEATURES_FAM10h_REV_C_ECX; + feat_edx = AMD_FEATURES_FAM10h_REV_C_EDX; + extfeat_ecx = AMD_EXTFEATURES_FAM10h_REV_C_ECX; + extfeat_edx = AMD_EXTFEATURES_FAM10h_REV_C_EDX; + }else if (!strcmp (opt_famrev,"fam_11_rev_b" )) { + feat_ecx = AMD_FEATURES_FAM11h_REV_B_ECX; + feat_edx = AMD_FEATURES_FAM11h_REV_B_EDX; + extfeat_ecx = AMD_EXTFEATURES_FAM11h_REV_B_ECX; + extfeat_edx = AMD_EXTFEATURES_FAM11h_REV_B_EDX; + }else { +printk ("Invalid processor string: %s\n" , opt_famrev); +printk ("CPUID will not be masked\n" ); +return ; + } +/* Otherwise, check if we were given specific masking values. */ + }else if (opt_cpuid_mask_ecx | opt_cpuid_mask_edx | + opt_cpuid_mask_ext_ecx | opt_cpuid_mask_ext_edx) { + feat_ecx = opt_cpuid_mask_ecx ? : ~0U ; + feat_edx = opt_cpuid_mask_edx ? : ~0U ; + extfeat_ecx = opt_cpuid_mask_ext_ecx ? : ~0U ; + extfeat_edx = opt_cpuid_mask_ext_edx ? : ~0U ; + }else { +/* Silently do nothing. */ +return ; + } + +printk ("Writing CPUID feature mask ECX:EDX -> %08Xh:%08Xh\n" , + feat_ecx, feat_edx); +printk ("Writing CPUID extended feature mask ECX:EDX -> %08Xh:%08Xh\n" , + extfeat_ecx, extfeat_edx); + +/* AMD processors prior to family 10h required a 32-bit password */ +if (c->x86 >=0x10 ) { +wrmsr (MSR_K8_FEATURE_MASK , feat_edx, feat_ecx); +wrmsr (MSR_K8_EXT_FEATURE_MASK , extfeat_edx, extfeat_ecx); + }else if (c->x86 ==0x0f ) { +wrmsr_amd (MSR_K8_FEATURE_MASK , feat_edx, feat_ecx); +wrmsr_amd (MSR_K8_EXT_FEATURE_MASK , extfeat_edx, extfeat_ecx); + } +}/* * amd_flush_filter={on,off}. Forcibly Enable or disable the TLB flush
@@ -368,6 +497,8 @@if ((smp_processor_id () ==1 ) &&c1_ramping_may_cause_clock_drift (c))disable_c1_ramping (); +set_cpuidmask (c); +start_svm (c); }
xen/arch/x86/cpu/amd.h new file +103 -0
103 lines not on this page · raw message
xen/include/asm-x86/msr-index.h +3 -0
@@ -186,6 +186,9 @@#define MSR_K8_ENABLE_C1E 0xc0010055#define MSR_K8_VM_CR 0xc0010114#define MSR_K8_VM_HSAVE_PA 0xc0010117 + +#define MSR_K8_FEATURE_MASK 0xc0011004 +#define MSR_K8_EXT_FEATURE_MASK 0xc0011005/* MSR_K8_VM_CR bits: */ #define _K8_VMCR_SVME_DISABLE 4
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel