[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 3/3] x86/vmx: fix vmentry failure with TSX bits in LBR
On 21/02/17 09:13, Tian, Kevin wrote: >> @@ -2618,6 +2630,56 @@ static const struct lbr_info >> *last_branch_msr_get(void) >> return NULL; >> } >> >> +enum >> +{ >> + LBR_FORMAT_32 = 0x0, /* 32-bit record format */ >> + LBR_FORMAT_LIP = 0x1, /* 64-bit LIP record format */ >> + LBR_FORMAT_EIP = 0x2, /* 64-bit EIP record format */ >> + LBR_FORMAT_EIP_FLAGS = 0x3, /* 64-bit EIP, Flags */ >> + LBR_FORMAT_EIP_FLAGS_TSX = 0x4, /* 64-bit EIP, Flags, TSX */ >> + LBR_FORMAT_EIP_FLAGS_TSX_INFO = 0x5, /* 64-bit EIP, Flags, TSX, >> LBR_INFO */ >> + LBR_FORMAT_EIP_FLAGS_CYCLES = 0x6, /* 64-bit EIP, Flags, Cycles */ >> +}; >> + >> +#define LBR_FROM_SIGNEXT_2MSB ((1ULL << 59) | (1ULL << 60)) >> + >> +static bool __read_mostly vmx_lbr_tsx_fixup_needed; >> +static uint32_t __read_mostly lbr_from_start; >> +static uint32_t __read_mostly lbr_from_end; >> +static uint32_t __read_mostly lbr_lastint_from; >> + >> +static void __init vmx_lbr_tsx_fixup_check(void) >> +{ >> + bool tsx_support = cpu_has_hle || cpu_has_rtm; >> + uint64_t caps; >> + uint32_t lbr_format; >> + >> + /* Fixup is needed only when TSX support is disabled ... */ >> + if ( tsx_support ) >> + return; > !tsx_support The original code is correct. This problem only manifests when TSX is unavailable. > >> + >> + if ( !cpu_has_pdcm ) >> + return; > combine two ifs into one > >> + >> + rdmsrl(MSR_IA32_PERF_CAPABILITIES, caps); >> + lbr_format = caps & LBR_FORMAT_MSR_IA32_PERF_CAP; >> + >> + /* ... and the address format of LBR includes TSX bits 61:62 */ > what's "..."? From the previous comment. > >> + if ( lbr_format == LBR_FORMAT_EIP_FLAGS_TSX ) >> + { >> + const struct lbr_info *lbr = last_branch_msr_get(); >> + >> + if ( lbr == NULL ) >> + return; > move above check before rdmsrl. At least avoid one unnecessary > msr read when LBR is not available. Which check and which rdmsr? In reality, if cpu_has_pdcm is set, we would always expect to have LBR. > >> + >> + lbr_lastint_from = lbr[LBR_LASTINT_FROM_IDX].base; >> + lbr_from_start = lbr[LBR_LASTBRANCH_FROM_IDX].base; >> + lbr_from_end = lbr_from_start + lbr[LBR_LASTBRANCH_FROM_IDX].count; >> + >> + vmx_lbr_tsx_fixup_needed = true; >> + } >> +} >> + >> static int is_last_branch_msr(u32 ecx) >> { >> const struct lbr_info *lbr = last_branch_msr_get(); >> @@ -2876,7 +2938,11 @@ static int vmx_msr_write_intercept(unsigned int msr, >> uint64_t >> msr_content) >> for ( ; (rc == 0) && lbr->count; lbr++ ) >> for ( i = 0; (rc == 0) && (i < lbr->count); i++ ) >> if ( (rc = vmx_add_guest_msr(lbr->base + i)) == 0 ) >> + { >> vmx_disable_intercept_for_msr(v, lbr->base + i, >> MSR_TYPE_R | >> MSR_TYPE_W); >> + if ( vmx_lbr_tsx_fixup_needed ) >> + v->arch.hvm_vmx.lbr_tsx_fixup_enabled = true; >> + } >> } >> >> if ( (rc < 0) || >> @@ -3897,6 +3963,27 @@ out: >> } >> } >> >> +static void vmx_lbr_tsx_fixup(void) >> +{ >> + struct vcpu *curr = current; >> + unsigned int msr_count = curr->arch.hvm_vmx.msr_count; >> + struct vmx_msr_entry *msr_area = curr->arch.hvm_vmx.msr_area; >> + struct vmx_msr_entry *msr; >> + >> + if ( (msr = vmx_find_msr(lbr_from_start, VMX_GUEST_MSR)) != NULL ) > Curious whether NULL is a valid situation here. If not we need handle it. > Otherwise please ignore this comment. It is safer in the case that this function gets called and there are no LBR MSRs in the load list. ~Andrew _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |