All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Mi, Dapeng" <dapeng1.mi@linux.intel.com>
To: Sean Christopherson <seanjc@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	Jim Mattson <jmattson@google.com>,
	Mingwei Zhang <mizhang@google.com>,
	Xiong Zhang <xiong.y.zhang@intel.com>,
	Zhenyu Wang <zhenyuw@linux.intel.com>,
	Like Xu <like.xu.linux@gmail.com>,
	Jinrong Liang <cloudliang@tencent.com>,
	Yongwei Ma <yongwei.ma@intel.com>,
	Dapeng Mi <dapeng1.mi@intel.com>, Gleb Natapov <gleb@redhat.com>
Subject: Re: [PATCH] KVM: x86/pmu: Return KVM_MSR_RET_INVALID for invalid PMU MSR access
Date: Wed, 10 Jul 2024 11:13:32 +0800	[thread overview]
Message-ID: <2205c1fc-e7c5-48aa-ac06-345227cc9bbb@linux.intel.com> (raw)
In-Reply-To: <Zo2FYieeerQzUGOa@google.com>


On 7/10/2024 2:45 AM, Sean Christopherson wrote:
> On Tue, Jul 09, 2024, Dapeng Mi wrote:
>> Return KVM_MSR_RET_INVALID instead of 0 to inject #GP to guest for all
>> invalid PMU MSRs access
>>
>> Currently KVM silently drops the access and doesn't inject #GP for some
>> invalid PMU MSRs like MSR_P6_PERFCTR0/MSR_P6_PERFCTR1,
>> MSR_P6_EVNTSEL0/MSR_P6_EVNTSEL1, but KVM still injects #GP for all other
>> invalid PMU MSRs. This leads to guest see different behavior on invalid
>> PMU access and may confuse guest.
> This is by design.  I'm not saying it's _good_ design, but it is very much
> intended.  More importantly, it's established behavior, i.e. having KVM inject
> #GP could break existing setups.
>
>> This behavior is introduced by the
>> 'commit 5753785fa977 ("KVM: do not #GP on perf MSR writes when vPMU is disabled")'
>> in 2012. This commit seems to want to keep back compatible with weird
>> behavior of some guests in vPMU disabled case,
> Ya, because at the time, guest kernels hadn't been taught to play nice with
> unexpected virtualization setups, i.e. VMs without PMUs.
>
>> but strongly suspect if it's still available nowadays.
> I don't follow this comment.
>
>> Since Perfmon v6 starts, the GP counters could become discontinuous on
>> HW, It's possible that HW doesn't support GP counters 0 and 1.
>> Considering this situation KVM should inject #GP for all invalid PMU MSRs
>> access.
> IIUC, the behavior you want is inject a #GP if the vCPU has a PMU and the MSR is
> not valid.  We can do that and still maintain backwards compatibility, hopefully
> without too much ugliness (maybe even an improvement!).
>
> This? (completely untested)

Seems no better method. Would adopt this. Thanks.

>
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 5aa7581802f7..b5e95e5f1f32 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -4063,9 +4063,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>         case MSR_P6_PERFCTR0 ... MSR_P6_PERFCTR1:
>         case MSR_K7_EVNTSEL0 ... MSR_K7_EVNTSEL3:
>         case MSR_P6_EVNTSEL0 ... MSR_P6_EVNTSEL1:
> -               if (kvm_pmu_is_valid_msr(vcpu, msr))
> -                       return kvm_pmu_set_msr(vcpu, msr_info);
> -
> +               if (vcpu_to_pmu(vcpu)->version)
> +                       goto default_handler;
>                 if (data)
>                         kvm_pr_unimpl_wrmsr(vcpu, msr, data);
>                 break;
> @@ -4146,6 +4145,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>                 break;
>  #endif
>         default:
> +default_handler:
>                 if (kvm_pmu_is_valid_msr(vcpu, msr))
>                         return kvm_pmu_set_msr(vcpu, msr_info);
>  
> @@ -4251,8 +4251,8 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>         case MSR_K7_PERFCTR0 ... MSR_K7_PERFCTR3:
>         case MSR_P6_PERFCTR0 ... MSR_P6_PERFCTR1:
>         case MSR_P6_EVNTSEL0 ... MSR_P6_EVNTSEL1:
> -               if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
> -                       return kvm_pmu_get_msr(vcpu, msr_info);
> +               if (vcpu_to_pmu(vcpu)->version)
> +                       goto default_handler;
>                 msr_info->data = 0;
>                 break;
>         case MSR_IA32_UCODE_REV:
> @@ -4505,6 +4505,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>                 break;
>  #endif
>         default:
> +default_handler:
>                 if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
>                         return kvm_pmu_get_msr(vcpu, msr_info);
>  
> diff --git a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c
> index 96446134c00b..0de606b542ac 100644
> --- a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c
> @@ -344,7 +344,8 @@ static void guest_test_rdpmc(uint32_t rdpmc_idx, bool expect_success,
>  static void guest_rd_wr_counters(uint32_t base_msr, uint8_t nr_possible_counters,
>                                  uint8_t nr_counters, uint32_t or_mask)
>  {
> -       const bool pmu_has_fast_mode = !guest_get_pmu_version();
> +       const u8 pmu_version = guest_get_pmu_version();
> +       const bool pmu_has_fast_mode = !pmu_version;
>         uint8_t i;
>  
>         for (i = 0; i < nr_possible_counters; i++) {
> @@ -363,12 +364,13 @@ static void guest_rd_wr_counters(uint32_t base_msr, uint8_t nr_possible_counters
>                 const bool expect_success = i < nr_counters || (or_mask & BIT(i));
>  
>                 /*
> -                * KVM drops writes to MSR_P6_PERFCTR[0|1] if the counters are
> -                * unsupported, i.e. doesn't #GP and reads back '0'.
> +                * KVM drops writes to MSR_P6_PERFCTR[0|1] if the vCPU doesn't
> +                * have a PMU, i.e. doesn't #GP and reads back '0'.
>                  */
>                 const uint64_t expected_val = expect_success ? test_val : 0;
> -               const bool expect_gp = !expect_success && msr != MSR_P6_PERFCTR0 &&
> -                                      msr != MSR_P6_PERFCTR1;
> +               const bool expect_gp = !expect_success &&
> +                                      (pmu_version ||
> +                                       (msr != MSR_P6_PERFCTR0 && msr != MSR_P6_PERFCTR1));
>                 uint32_t rdpmc_idx;
>                 uint8_t vector;
>                 uint64_t val;
>

      reply	other threads:[~2024-07-10  3:13 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-09 14:55 [PATCH] KVM: x86/pmu: Return KVM_MSR_RET_INVALID for invalid PMU MSR access Dapeng Mi
2024-07-09 18:45 ` Sean Christopherson
2024-07-10  3:13   ` Mi, Dapeng [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2205c1fc-e7c5-48aa-ac06-345227cc9bbb@linux.intel.com \
    --to=dapeng1.mi@linux.intel.com \
    --cc=cloudliang@tencent.com \
    --cc=dapeng1.mi@intel.com \
    --cc=gleb@redhat.com \
    --cc=jmattson@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=like.xu.linux@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mizhang@google.com \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=xiong.y.zhang@intel.com \
    --cc=yongwei.ma@intel.com \
    --cc=zhenyuw@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.