[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] x86/AMD: Add support for AMD's OSVW feature in guests
>>> On 16.01.12 at 22:11, Boris Ostrovsky <boris.ostrovsky@xxxxxxx> wrote: > --- a/tools/libxc/xc_cpuid_x86.c Mon Jan 09 16:01:44 2012 +0100 > +++ b/tools/libxc/xc_cpuid_x86.c Mon Jan 16 22:08:09 2012 +0100 > @@ -108,6 +108,7 @@ static void amd_xc_cpuid_policy( > bitmaskof(X86_FEATURE_SSE4A) | > bitmaskof(X86_FEATURE_MISALIGNSSE) | > bitmaskof(X86_FEATURE_3DNOWPREFETCH) | > + bitmaskof(X86_FEATURE_OSVW) | Indentation. Also, is this really meaningful to PV guests? And valid for pre-Fam10? > bitmaskof(X86_FEATURE_XOP) | > bitmaskof(X86_FEATURE_FMA4) | > bitmaskof(X86_FEATURE_TBM) | > --- a/xen/arch/x86/cpu/amd.c Mon Jan 09 16:01:44 2012 +0100 > +++ b/xen/arch/x86/cpu/amd.c Mon Jan 16 22:08:09 2012 +0100 > @@ -32,6 +32,13 @@ > static char opt_famrev[14]; > string_param("cpuid_mask_cpu", opt_famrev); > > +/* > + * Set osvw_len to higher number when updated Revision Guides > + * are published and we know what the new status bits are > + */ This is ugly, as it requires permanent attention. The value to start with should really be 64 (beyond which other code adjustments are going to be necessary anyway). > +static uint64_t osvw_length = 4, osvw_status; > +static DEFINE_SPINLOCK(amd_lock); > + > static inline void wrmsr_amd(unsigned int index, unsigned int lo, > unsigned int hi) > { > @@ -182,6 +189,35 @@ static void __devinit set_cpuidmask(cons > } > } > > +static void amd_guest_osvw_init(struct vcpu *vcpu) > +{ > + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) > + return; Shouldn't we bail here for pre-Fam10 CPUs too? Further, as asked above already - is all this really meaningful to PV guests? Otherwise the code would better go somewhere under xen/arch/x86/hvm/svm/ ... Also, throughout this file indentation needs to be changed to Linux style (tabs instead of spaces), unless you want to contribute a patch to convert the whole file to Xen style (in which case you'd still need to make adjustments here). > + > + /* > + * Guests should see errata 400 and 415 as fixed (assuming that > + * HLT and IO instructions are intercepted). > + */ > + vcpu->arch.amd.osvw.length = (osvw_length >= 3) ? (osvw_length) : 3; An expression consisting of just an identifier for sure doesn't need parentheses. > + vcpu->arch.amd.osvw.status = osvw_status & ~(6ULL); > + > + /* > + * By increasing VCPU's osvw.length to 3 we are telling the guest that > + * all osvw.status bits inside that length, including bit 0 (which is > + * reserved for erratum 298), are valid. However, if host processor's > + * osvw_len is 0 then osvw_status[0] carries no information. We need to > + * be conservative here and therefore we tell the guest that erratum 298 > + * is present (because we really don't know). > + */ > + if (osvw_length == 0 && boot_cpu_data.x86 == 0x10) Why do you check the family here? If osvw_length can only ever be zero on Fam10, then the first check is sufficient. If osvw_length can be zero on other than Fam10 (no matter whether we bail early older CPUs), then the check is actually wrong. > + vcpu->arch.amd.osvw.status |= 1; > +} > + > +void amd_vcpu_initialise(struct vcpu *vcpu) > +{ > + amd_guest_osvw_init(vcpu); > +} > + > /* > * Check for the presence of an AMD erratum. Arguments are defined in amd.h > > * for each known erratum. Return 1 if erratum is found. > @@ -512,6 +548,30 @@ static void __devinit init_amd(struct cp > set_cpuidmask(c); > > check_syscfg_dram_mod_en(); > + > + /* > + * Get OSVW bits. If bits are not the same on different processors then > + * choose the worst case (i.e. if erratum is present on one processor and > + * not on another assume that the erratum is present everywhere). > + */ > + if (test_bit(X86_FEATURE_OSVW, &boot_cpu_data.x86_capability)) { > + uint64_t len, status; > + > + if (rdmsr_safe(MSR_AMD_OSVW_ID_LENGTH, len) || > + rdmsr_safe(MSR_AMD_OSVW_STATUS, status)) > + len = status = 0; > + > + spin_lock(&amd_lock); What is the locking here supposed to protect against? The AP call tree is smp_callin() -> identify_cpu() -> init_amd(), which cannot race with anything (as the initiating processor is waiting for cpu_state to change to CPU_STATE_CALLIN). > + > + if (len < osvw_length) > + osvw_length = len; > + > + osvw_status |= status; > + osvw_status &= (1ULL << osvw_length) - 1; > + > + spin_unlock(&amd_lock); > + } else > + osvw_length = osvw_status = 0; > } > > static struct cpu_dev amd_cpu_dev __cpuinitdata = { > --- a/xen/arch/x86/domain.c Mon Jan 09 16:01:44 2012 +0100 > +++ b/xen/arch/x86/domain.c Mon Jan 16 22:08:09 2012 +0100 > @@ -422,6 +422,10 @@ int vcpu_initialise(struct vcpu *v) > if ( (rc = vcpu_init_fpu(v)) != 0 ) > return rc; > > + /* Vendor-specific initialization */ > + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) If you check the vendor here, you don't need to anywhere in the descendant functions. > + amd_vcpu_initialise(v); > + > if ( is_hvm_domain(d) ) > { > rc = hvm_vcpu_initialise(v); > --- a/xen/arch/x86/hvm/svm/svm.c Mon Jan 09 16:01:44 2012 +0100 > +++ b/xen/arch/x86/hvm/svm/svm.c Mon Jan 16 22:08:09 2012 +0100 > @@ -1044,6 +1044,27 @@ static void svm_init_erratum_383(struct > } > } > > +static int svm_handle_osvw(struct vcpu *v, uint32_t msr, uint64_t *val, uint > read) > +{ > + uint eax, ebx, ecx, edx; > + > + /* Guest OSVW support */ > + hvm_cpuid(0x80000001, &eax, &ebx, &ecx, &edx); > + if (!test_bit((X86_FEATURE_OSVW & 31), &ecx)) Formatting of changes to this file should be changed to Xen style. > + return -1; > + > + if (read) { > + if (msr == MSR_AMD_OSVW_ID_LENGTH) > + *val = v->arch.amd.osvw.length; > + else > + *val = v->arch.amd.osvw.status; > + } > + /* Writes are ignored */ > + > + return 0; > +} > + > + > static int svm_cpu_up(void) > { > uint64_t msr_content; > --- a/xen/arch/x86/traps.c Mon Jan 09 16:01:44 2012 +0100 > +++ b/xen/arch/x86/traps.c Mon Jan 16 22:08:09 2012 +0100 > @@ -2542,6 +2542,15 @@ static int emulate_privileged_op(struct > if ( wrmsr_safe(regs->ecx, msr_content) != 0 ) > goto fail; > break; > + case MSR_AMD_OSVW_ID_LENGTH: > + case MSR_AMD_OSVW_STATUS: > + if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD ) { > + if (!boot_cpu_has(X86_FEATURE_OSVW)) > + goto fail; > + else Bogus "else" after a "goto". And I wonder, provided there is some point in doing all this for PV guests in the first place, whether this shouldn't be kept getting handled by the default case. > + break; /* Writes are ignored */ > + } > + /* Fall through to default case */ > default: > if ( wrmsr_hypervisor_regs(regs->ecx, msr_content) ) > break; > @@ -2573,6 +2582,7 @@ static int emulate_privileged_op(struct > break; > > case 0x32: /* RDMSR */ > + Stray addition of a newline. > switch ( (u32)regs->ecx ) > { > #ifdef CONFIG_X86_64 > @@ -2632,6 +2642,23 @@ static int emulate_privileged_op(struct > regs->eax = (uint32_t)msr_content; > regs->edx = (uint32_t)(msr_content >> 32); > break; > + case MSR_AMD_OSVW_ID_LENGTH: > + case MSR_AMD_OSVW_STATUS: > + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { > + if (!boot_cpu_has(X86_FEATURE_OSVW)) > + goto fail; > + else { Bogus "else" after a "goto". Jan > + if ((u32)regs->ecx == MSR_AMD_OSVW_ID_LENGTH) > + msr_content = v->arch.amd.osvw.length; > + else > + msr_content = v->arch.amd.osvw.status; > + > + regs->eax = (uint32_t)msr_content; > + regs->edx = (uint32_t)(msr_content >> 32); > + } > + } else > + goto rdmsr_normal; > + break; > default: > if ( rdmsr_hypervisor_regs(regs->ecx, &val) ) > { _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |