|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH-v2] vpmu intel: Add cpuid handling when vpmu disabled
On 26/03/2013 11:16, "Dietmar Hahn" <dietmar.hahn@xxxxxxxxxxxxxx> wrote:
> Even though vpmu is disabled in the hypervisor in the HVM guest the call of
> cpuid(0xa) returns informations about usable performance counters.
> This may confuse guest software when trying to use the counters and nothing
> happens.
> This patch clears most bits in registers eax and edx of cpuid(0xa) instruction
> for the guest when vpmu is disabled:
> - version ID of architectural performance counting
> - number of general pmu registers
> - width of general pmu registers
> - number of fixed pmu registers
> - width of ixed pmu registers
>
> Thanks.
> Dietmar.
>
>
> Signed-off-by: Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxx>
Acked-by: Keir Fraser <keir@xxxxxxx>
> ---
>
> Changes from v1: As Konrad suggested I added a little bit more of
> documentation
> to the defines.
>
>
> diff -r 2246964a25a8 xen/arch/x86/hvm/svm/vpmu.c
> --- a/xen/arch/x86/hvm/svm/vpmu.c Mon Mar 25 16:57:31 2013 +0100
> +++ b/xen/arch/x86/hvm/svm/vpmu.c Tue Mar 26 12:01:11 2013 +0100
> @@ -370,6 +370,10 @@ int svm_vpmu_initialise(struct vcpu *v,
> uint8_t family = current_cpu_data.x86;
> int ret = 0;
>
> + /* vpmu enabled? */
> + if ( !vpmu_flags )
> + return 0;
> +
> switch ( family )
> {
> case 0x10:
> diff -r 2246964a25a8 xen/arch/x86/hvm/vmx/vpmu_core2.c
> --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c Mon Mar 25 16:57:31 2013 +0100
> +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c Tue Mar 26 12:01:11 2013 +0100
> @@ -731,6 +731,62 @@ struct arch_vpmu_ops core2_vpmu_ops = {
> .arch_vpmu_load = core2_vpmu_load
> };
>
> +/*
> + * See Intel SDM Vol 2a Instruction Set Referenc for CPUID instruction.
> + * cpuid 0xa - Architectural Performance Monitoring Leaf
> + * Register eax
> + */
> +#define X86_FEATURE_PMU_VER_OFF 0 /* Version ID */
> +#define FEATURE_PMU_VER_BITS 8 /* 8 bits 0..7 */
> +#define X86_FEATURE_NUM_GEN_OFF 8 /* Number of general pmu registers */
> +#define FEATURE_NUM_GEN_BITS 8 /* 8 bits 8..15 */
> +#define X86_FEATURE_GEN_WIDTH_OFF 16 /* Width of general pmu registers */
> +#define FEATURE_GEN_WIDTH_BITS 8 /* 8 bits 16..23 */
> +/* Register edx */
> +#define X86_FEATURE_NUM_FIX_OFF 0 /* Number of fixed pmu registers */
> +#define FEATURE_NUM_FIX_BITS 5 /* 5 bits 0..4 */
> +#define X86_FEATURE_FIX_WIDTH_OFF 5 /* Width of fixed pmu registers */
> +#define FEATURE_FIX_WIDTH_BITS 8 /* 8 bits 5..12 */
> +
> +static void core2_no_vpmu_do_cpuid(unsigned int input,
> + unsigned int *eax, unsigned int *ebx,
> + unsigned int *ecx, unsigned int *edx)
> +{
> + /*
> + * As in this case the vpmu is not enabled reset some bits in the
> + * architectural performance monitoring related part.
> + */
> + if ( input == 0xa )
> + {
> + *eax &= ~(((1 << FEATURE_PMU_VER_BITS) -1) <<
> X86_FEATURE_PMU_VER_OFF);
> + *eax &= ~(((1 << FEATURE_NUM_GEN_BITS) -1) <<
> X86_FEATURE_NUM_GEN_OFF);
> + *eax &= ~(((1 << FEATURE_GEN_WIDTH_BITS) -1) <<
> X86_FEATURE_GEN_WIDTH_OFF);
> +
> + *edx &= ~(((1 << FEATURE_NUM_FIX_BITS) -1) <<
> X86_FEATURE_NUM_FIX_OFF);
> + *edx &= ~(((1 << FEATURE_FIX_WIDTH_BITS) -1) <<
> X86_FEATURE_FIX_WIDTH_OFF);
> + }
> +}
> +
> +/*
> + * If its a vpmu msr set it to 0.
> + */
> +static int core2_no_vpmu_do_rdmsr(unsigned int msr, uint64_t *msr_content)
> +{
> + int type = -1, index = -1;
> + if ( !is_core2_vpmu_msr(msr, &type, &index) )
> + return 0;
> + *msr_content = 0;
> + return 1;
> +}
> +
> +/*
> + * These functions are used in case vpmu is not enabled.
> + */
> +struct arch_vpmu_ops core2_no_vpmu_ops = {
> + .do_rdmsr = core2_no_vpmu_do_rdmsr,
> + .do_cpuid = core2_no_vpmu_do_cpuid,
> +};
> +
> int vmx_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags)
> {
> struct vpmu_struct *vpmu = vcpu_vpmu(v);
> @@ -738,6 +794,10 @@ int vmx_vpmu_initialise(struct vcpu *v,
> uint8_t cpu_model = current_cpu_data.x86_model;
> int ret = 0;
>
> + vpmu->arch_vpmu_ops = &core2_no_vpmu_ops;
> + if ( !vpmu_flags )
> + return 0;
> +
> if ( family == 6 )
> {
> switch ( cpu_model )
> diff -r 2246964a25a8 xen/arch/x86/hvm/vpmu.c
> --- a/xen/arch/x86/hvm/vpmu.c Mon Mar 25 16:57:31 2013 +0100
> +++ b/xen/arch/x86/hvm/vpmu.c Tue Mar 26 12:01:11 2013 +0100
> @@ -67,7 +67,7 @@ int vpmu_do_wrmsr(unsigned int msr, uint
> {
> struct vpmu_struct *vpmu = vcpu_vpmu(current);
>
> - if ( vpmu->arch_vpmu_ops )
> + if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->do_wrmsr )
> return vpmu->arch_vpmu_ops->do_wrmsr(msr, msr_content);
> return 0;
> }
> @@ -76,7 +76,7 @@ int vpmu_do_rdmsr(unsigned int msr, uint
> {
> struct vpmu_struct *vpmu = vcpu_vpmu(current);
>
> - if ( vpmu->arch_vpmu_ops )
> + if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->do_rdmsr )
> return vpmu->arch_vpmu_ops->do_rdmsr(msr, msr_content);
> return 0;
> }
> @@ -85,7 +85,7 @@ int vpmu_do_interrupt(struct cpu_user_re
> {
> struct vpmu_struct *vpmu = vcpu_vpmu(current);
>
> - if ( vpmu->arch_vpmu_ops )
> + if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->do_interrupt )
> return vpmu->arch_vpmu_ops->do_interrupt(regs);
> return 0;
> }
> @@ -104,7 +104,7 @@ void vpmu_save(struct vcpu *v)
> {
> struct vpmu_struct *vpmu = vcpu_vpmu(v);
>
> - if ( vpmu->arch_vpmu_ops )
> + if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->arch_vpmu_save )
> vpmu->arch_vpmu_ops->arch_vpmu_save(v);
> }
>
> @@ -112,7 +112,7 @@ void vpmu_load(struct vcpu *v)
> {
> struct vpmu_struct *vpmu = vcpu_vpmu(v);
>
> - if ( vpmu->arch_vpmu_ops )
> + if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->arch_vpmu_load )
> vpmu->arch_vpmu_ops->arch_vpmu_load(v);
> }
>
> @@ -121,9 +121,6 @@ void vpmu_initialise(struct vcpu *v)
> struct vpmu_struct *vpmu = vcpu_vpmu(v);
> uint8_t vendor = current_cpu_data.x86_vendor;
>
> - if ( !opt_vpmu_enabled )
> - return;
> -
> if ( vpmu_is_set(vpmu, VPMU_CONTEXT_ALLOCATED) )
> vpmu_destroy(v);
> vpmu_clear(vpmu);
> @@ -153,7 +150,7 @@ void vpmu_destroy(struct vcpu *v)
> {
> struct vpmu_struct *vpmu = vcpu_vpmu(v);
>
> - if ( vpmu->arch_vpmu_ops )
> + if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->arch_vpmu_destroy )
> vpmu->arch_vpmu_ops->arch_vpmu_destroy(v);
> }
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |