kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Xiaoyao Li <xiaoyao.li@intel.com>
To: Jim Mattson <jmattson@google.com>,
	Sean Christopherson <sean.j.christopherson@intel.com>
Cc: kvm list <kvm@vger.kernel.org>,
	Steve Rutherford <srutherford@google.com>,
	Jacob Xu <jacobhxu@google.com>, Peter Shier <pshier@google.com>
Subject: Re: [RFC][PATCH] kvm: x86: Improve emulation of CPUID leaves 0BH and 1FH
Date: Thu, 19 Sep 2019 13:31:29 +0800	[thread overview]
Message-ID: <b3ebf989-8da9-6fa6-9296-ec694988e645@intel.com> (raw)
In-Reply-To: <CALMp9eSJkjO0CX2_s1QpgaYk-pDVCYoof_QVjxf9cpquaMOr1A@mail.gmail.com>

On 9/19/2019 2:41 AM, Jim Mattson wrote:
> On Wed, Sep 18, 2019 at 11:22 AM Jim Mattson <jmattson@google.com> wrote:
[...]>>>
>>> If I'm reading the code correctly, this is fragile and subtle.  The order
>>> of cpuid entries is controlled by userspace, which means that clearing
>>> KVM_CPUID_FLAG_SIGNIFCANT_INDEX depends on this entry being kept after all
>>> other entries for this function.  In practice I'm guessing userspaces
>>> naturally sort entries with the same function by ascending index, but it
>>> seems like avoidable issue.
>>
>> Though not documented, the CPUID leaf matching code has always
>> depended on ordering.
>>
>>> Also, won't matching the last entry generate the wrong values for EAX, EBX
>>> and ECX, i.e. the valid values for the last index instead of zeroes?
>>
>> This entry has CH==0. According to the SDM, "For sub-leaves that
>> return an invalid level-type of 0 in ECX[15:8]; EAX and EBX will
>> return 0."
>> ECX[7:0] will be wrong, but that's fixed up by the flag below.
>> ECX[31:16] are reserved and perhaps should be cleared here, but I'm
>> not sure how I would interpret it if those bits started being non-zero
>> for the first leaf with CH==0.
>>
>>>> +                     entry[i - 1].flags |= KVM_CPUID_FLAG_CL_IS_PASSTHROUGH;
>>>
>>> Lastly, do we actually need to enumerate this silliness to userspace?
>>> What if we handle this as a one-off case in CPUID emulation and avoid the
>>> ABI breakage that way?  E.g.:
>>>
>>> diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
>>> index dd5985eb61b4..aaf5cdcb88c9 100644
>>> --- a/arch/x86/kvm/cpuid.c
>>> +++ b/arch/x86/kvm/cpuid.c
>>> @@ -1001,6 +1001,16 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
>>>          }
>>>
>>>   out:
>>> +       if (!best && (function == 0xb || function == 0x1f)) {
>>> +               best = check_cpuid_limit(vcpu, function, 0);
>>> +               if (best) {
>>> +                       *eax = 0;
>>> +                       *ebx = 0;
>>> +                       *ecx &= 0xff;
>>> +                       *edx = *best->edx;
>>> +               }
>>> +       }
>>> +
>>

Hi Sean,
your proposal above seems not work. check_cpuid_limit(vcpu, 0xb/01f, 0) 
always return NULL, if there are valid 0xb/0x1f leaves in 
vcpu->arch.cpuid_entries[] (maxBaiscleaf >= 0xb/0x1f)

>> Aside from the fact that one should never call check_cpuid_limit on
>> AMD systems (they don't do the "last basic leaf" nonsense), an
>> approach like this should work.
> 
> The above proposal doesn't correctly handle a leaf outside of ([0,
> maxBasicLeaf] union [80000000H, maxExtendedLeaf]) , where maxBasicLeaf
> == (0BH or 1FH) on Intel hardware...but it could be fixed up to do so,
> if hard-coding this behavior in kvm_cpuid() is preferable to the API
> breakage.
> 

I vote for Sean's one-off case, how about something like this:

diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 22c2720cd948..6af5febf7b12 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -976,11 +976,23 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, 
u32 *ebx,
                u32 *ecx, u32 *edx, bool check_limit)
  {
         u32 function = *eax, index = *ecx;
-       struct kvm_cpuid_entry2 *best;
+       struct kvm_cpuid_entry2 *best, tmp;
         bool entry_found = true;

         best = kvm_find_cpuid_entry(vcpu, function, index);

+       if (!best && (fuction == 0xb || function == 0x1f) && index > 0) {
+               best = kvm_find_cpuid_entry(vcpu, function, 0);
+               if (best) {
+                       tmp.eax = 0;
+                       tmp.ebx = 0;
+                       tmp.ecx = index & 0xff;
+                       tmp.edx = best->edx;
+                       best = &tmp;
+                       goto out;
+               }
+       }
+

  reply	other threads:[~2019-09-19  5:31 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-12 23:27 [RFC][PATCH] kvm: x86: Improve emulation of CPUID leaves 0BH and 1FH Jim Mattson
2019-09-18 15:32 ` Jim Mattson
2019-09-18 17:43 ` Sean Christopherson
2019-09-18 18:22   ` Jim Mattson
2019-09-18 18:41     ` Jim Mattson
2019-09-19  5:31       ` Xiaoyao Li [this message]
2019-09-19 18:26         ` Jim Mattson
2019-09-24 14:01     ` Paolo Bonzini

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=b3ebf989-8da9-6fa6-9296-ec694988e645@intel.com \
    --to=xiaoyao.li@intel.com \
    --cc=jacobhxu@google.com \
    --cc=jmattson@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=pshier@google.com \
    --cc=sean.j.christopherson@intel.com \
    --cc=srutherford@google.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).