On Wed, Nov 28, 2012 at 10:29 AM, Auld, Will <will.a...@intel.com> wrote:
> Thanks Marcelo, > > I'll address these items. > > >- Please rebase against queue branch on kvm.git. > > I am not sure how to do this. The repository I have been working against > is: > > git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git > > I assume that I need to change this in some way but I am not sure what I > need to do. Will you explain or give me the needed path? > http://www.linux-kvm.org/page/Code You should use this tree: git://git.kernel.org/pub/scm/virt/kvm/kvm.git > > Thanks, > > Will > > > -----Original Message----- > > From: Marcelo Tosatti [mailto:mtosa...@redhat.com] > > Sent: Tuesday, November 27, 2012 5:00 PM > > To: Auld, Will > > Cc: k...@vger.kernel.org; Dugger, Donald D; Liu, Jinsong; Zhang, > > Xiantao; a...@redhat.com; qemu-devel; Gleb > > Subject: Re: [PATCH V5 2/2] Enabling IA32_TSC_ADJUST for KVM guest VM > > support > > > > > > Hi Will, > > > > On Tue, Nov 27, 2012 at 11:09:00AM -0800, Will Auld wrote: > > > CPUID.7.0.EBX[1]=1 indicates IA32_TSC_ADJUST MSR 0x3b is supported > > > > > > Basic design is to emulate the MSR by allowing reads and writes to a > > > guest vcpu specific location to store the value of the emulated MSR > > > while adding the value to the vmcs tsc_offset. In this way the > > > IA32_TSC_ADJUST value will be included in all reads to the TSC MSR > > > whether through rdmsr or rdtsc. This is of course as long as the "use > > > TSC counter offsetting" VM-execution control is enabled as well as > > the IA32_TSC_ADJUST control. > > > > > > However, because hardware will only return the TSC + IA32_TSC_ADJUST > > + > > > vmsc tsc_offset for a guest process when it does and rdtsc (with the > > > correct > > > settings) the value of our virtualized IA32_TSC_ADJUST must be stored > > > in one of these three locations. The argument against storing it in > > > the actual MSR is performance. This is likely to be seldom used while > > > the save/restore is required on every transition. IA32_TSC_ADJUST was > > > created as a way to solve some issues with writing TSC itself so that > > is not an option either. > > > The remaining option, defined above as our solution has the problem > > of > > > returning incorrect vmcs tsc_offset values (unless we intercept and > > > fix, not done here) as mentioned above. However, more problematic is > > > that storing the data in vmcs tsc_offset will have a different > > > semantic effect on the system than does using the actual MSR. This is > > illustrated in the following example: > > > The hypervisor set the IA32_TSC_ADJUST, then the guest sets it and a > > > guest process performs a rdtsc. In this case the guest process will > > > get TSC + IA32_TSC_ADJUST_hyperviser + vmsc tsc_offset including > > IA32_TSC_ADJUST_guest. > > > While the total system semantics changed the semantics as seen by the > > > guest do not and hence this will not cause a problem. > > > > > > Signed-off-by: Will Auld <will.a...@intel.com> > > > --- > > > arch/x86/include/asm/cpufeature.h | 1 + > > > arch/x86/include/asm/kvm_host.h | 3 +++ > > > arch/x86/include/asm/msr-index.h | 1 + > > > arch/x86/kvm/cpuid.c | 2 ++ > > > arch/x86/kvm/cpuid.h | 8 ++++++++ > > > arch/x86/kvm/svm.c | 7 +++++++ > > > arch/x86/kvm/vmx.c | 9 +++++++++ > > > arch/x86/kvm/x86.c | 22 ++++++++++++++++++++++ > > > 8 files changed, 53 insertions(+) > > > > > > diff --git a/arch/x86/include/asm/cpufeature.h > > > b/arch/x86/include/asm/cpufeature.h > > > index 6b7ee5f..e574d81 100644 > > > --- a/arch/x86/include/asm/cpufeature.h > > > +++ b/arch/x86/include/asm/cpufeature.h > > > @@ -199,6 +199,7 @@ > > > > > > /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word > > 9 */ > > > #define X86_FEATURE_FSGSBASE (9*32+ 0) /* {RD/WR}{FS/GS}BASE > > instructions*/ > > > +#define X86_FEATURE_TSC_ADJUST (9*32+ 1) /* TSC adjustment MSR 0x3b > > > +*/ > > > #define X86_FEATURE_BMI1 (9*32+ 3) /* 1st group bit manipulation > > extensions */ > > > #define X86_FEATURE_HLE (9*32+ 4) /* Hardware Lock Elision > > */ > > > #define X86_FEATURE_AVX2 (9*32+ 5) /* AVX2 instructions */ > > > diff --git a/arch/x86/include/asm/kvm_host.h > > > b/arch/x86/include/asm/kvm_host.h index da34027..cf8c7e0 100644 > > > --- a/arch/x86/include/asm/kvm_host.h > > > +++ b/arch/x86/include/asm/kvm_host.h > > > @@ -442,6 +442,8 @@ struct kvm_vcpu_arch { > > > u32 virtual_tsc_mult; > > > u32 virtual_tsc_khz; > > > > > > + s64 ia32_tsc_adjust_msr; > > > + > > > atomic_t nmi_queued; /* unprocessed asynchronous NMIs */ > > > unsigned nmi_pending; /* NMI queued after currently running > > handler */ > > > bool nmi_injected; /* Trying to inject an NMI this entry */ > > > @@ -690,6 +692,7 @@ struct kvm_x86_ops { > > > bool (*has_wbinvd_exit)(void); > > > > > > void (*set_tsc_khz)(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool > > > scale); > > > + u64 (*read_tsc_offset)(struct kvm_vcpu *vcpu); > > > void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset); > > > > > > u64 (*compute_tsc_offset)(struct kvm_vcpu *vcpu, u64 target_tsc); > > > diff --git a/arch/x86/include/asm/msr-index.h > > > b/arch/x86/include/asm/msr-index.h > > > index 957ec87..6486569 100644 > > > --- a/arch/x86/include/asm/msr-index.h > > > +++ b/arch/x86/include/asm/msr-index.h > > > @@ -231,6 +231,7 @@ > > > #define MSR_IA32_EBL_CR_POWERON 0x0000002a > > > #define MSR_EBC_FREQUENCY_ID 0x0000002c > > > #define MSR_IA32_FEATURE_CONTROL 0x0000003a > > > +#define MSR_IA32_TSC_ADJUST 0x0000003b > > > > > > #define FEATURE_CONTROL_LOCKED (1<<0) > > > #define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1<<1) > > > diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index > > > 0595f13..e817bac 100644 > > > --- a/arch/x86/kvm/cpuid.c > > > +++ b/arch/x86/kvm/cpuid.c > > > @@ -320,6 +320,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 > > *entry, u32 function, > > > if (index == 0) { > > > entry->ebx &= kvm_supported_word9_x86_features; > > > cpuid_mask(&entry->ebx, 9); > > > + // TSC_ADJUST is emulated > > > + entry->ebx |= F(TSC_ADJUST); > > > } else > > > entry->ebx = 0; > > > entry->eax = 0; > > > diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index > > > a10e460..3a8b504 100644 > > > --- a/arch/x86/kvm/cpuid.h > > > +++ b/arch/x86/kvm/cpuid.h > > > @@ -28,6 +28,14 @@ static inline bool guest_cpuid_has_xsave(struct > > kvm_vcpu *vcpu) > > > return best && (best->ecx & bit(X86_FEATURE_XSAVE)); } > > > > > > +static inline bool guest_cpuid_has_tsc_adjust(struct kvm_vcpu *vcpu) > > > +{ > > > + struct kvm_cpuid_entry2 *best; > > > + > > > + best = kvm_find_cpuid_entry(vcpu, 7, 0); > > > + return best && (best->ebx & bit(X86_FEATURE_TSC_ADJUST)); } > > > + > > > static inline bool guest_cpuid_has_smep(struct kvm_vcpu *vcpu) { > > > struct kvm_cpuid_entry2 *best; > > > diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index > > > 5ac11f0..7f5e6eb 100644 > > > --- a/arch/x86/kvm/svm.c > > > +++ b/arch/x86/kvm/svm.c > > > @@ -1012,6 +1012,12 @@ static void svm_set_tsc_khz(struct kvm_vcpu > > *vcpu, u32 user_tsc_khz, bool scale) > > > svm->tsc_ratio = ratio; > > > } > > > > > > +static u64 svm_read_tsc_offset(struct kvm_vcpu *vcpu) { > > > + struct vcpu_svm *svm = to_svm(vcpu); > > > + return svm->vmcb->control.tsc_offset; } > > > + > > > static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) > > > { > > > struct vcpu_svm *svm = to_svm(vcpu); @@ -4333,6 +4339,7 @@ static > > > struct kvm_x86_ops svm_x86_ops = { > > > .has_wbinvd_exit = svm_has_wbinvd_exit, > > > > > > .set_tsc_khz = svm_set_tsc_khz, > > > + .read_tsc_offset = svm_read_tsc_offset, > > > .write_tsc_offset = svm_write_tsc_offset, > > > .adjust_tsc_offset = svm_adjust_tsc_offset, > > > .compute_tsc_offset = svm_compute_tsc_offset, diff --git > > > a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 819970f..0a73e72 > > > 100644 > > > --- a/arch/x86/kvm/vmx.c > > > +++ b/arch/x86/kvm/vmx.c > > > @@ -1861,6 +1861,11 @@ static void vmx_set_tsc_khz(struct kvm_vcpu > > *vcpu, u32 user_tsc_khz, bool scale) > > > WARN(1, "user requested TSC rate below hardware speed\n"); > > } > > > > > > +static u64 vmx_read_tsc_offset(struct kvm_vcpu *vcpu) { > > > + return vmcs_read64(TSC_OFFSET); > > > +} > > > + > > > /* > > > * writes 'offset' into guest's timestamp counter offset register > > > */ > > > @@ -2243,6 +2248,9 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, > > struct msr_data *msr_info) > > > } > > > ret = kvm_set_msr_common(vcpu, msr_info); > > > + case MSR_IA32_TSC_ADJUST: > > > + ret = kvm_set_msr_common(vcpu, msr_info); > > > + break; > > > case MSR_TSC_AUX: > > > if (!vmx->rdtscp_enabled) > > > return 1; > > > @@ -7338,6 +7346,7 @@ static struct kvm_x86_ops vmx_x86_ops = { > > > .has_wbinvd_exit = cpu_has_vmx_wbinvd_exit, > > > > > > .set_tsc_khz = vmx_set_tsc_khz, > > > + .read_tsc_offset = vmx_read_tsc_offset, > > > .write_tsc_offset = vmx_write_tsc_offset, > > > .adjust_tsc_offset = vmx_adjust_tsc_offset, > > > .compute_tsc_offset = vmx_compute_tsc_offset, diff --git > > > a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index edafa29..7c2990b > > > 100644 > > > --- a/arch/x86/kvm/x86.c > > > +++ b/arch/x86/kvm/x86.c > > > @@ -824,6 +824,7 @@ static u32 msrs_to_save[] = { static unsigned > > > num_msrs_to_save; > > > > > > static u32 emulated_msrs[] = { > > > + MSR_IA32_TSC_ADJUST, > > > MSR_IA32_TSCDEADLINE, > > > MSR_IA32_MISC_ENABLE, > > > MSR_IA32_MCG_STATUS, > > > @@ -1047,6 +1048,12 @@ static u64 compute_guest_tsc(struct kvm_vcpu > > *vcpu, s64 kernel_ns) > > > return tsc; > > > } > > > > > > +static void update_ia32_tsc_adjust_msr(struct kvm_vcpu *vcpu, s64 > > > +offset) { > > > + u64 curr_offset = kvm_x86_ops->read_tsc_offset(vcpu); > > > > Extra space. > > > > Other than that, looks fine. Remaining comments: > > > > - Basic functional test must be improved (testing that wrmsr(tsc, val) > > reflects on tsc_adjust and wrmsr(tsc_adjust_msr, val) reflects on tsc > > is enough. > > > > - Behaviour on reset: what is the behaviour on RESET? > > > > - Please rebase against queue branch on kvm.git. > > > > Thanks > > > > -- > To unsubscribe from this list: send the line "unsubscribe kvm" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html >