Received: by 2002:a25:c205:0:0:0:0:0 with SMTP id s5csp2978103ybf; Mon, 2 Mar 2020 20:09:37 -0800 (PST) X-Google-Smtp-Source: ADFU+vs+e4VkTN+9lNhc/+pcFJNVgnBcMmDT4uQdgjPYf6sdGtnPfKkhtOkU/AJJohkipRYzvELh X-Received: by 2002:aca:3189:: with SMTP id x131mr1218115oix.33.1583208577214; Mon, 02 Mar 2020 20:09:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1583208577; cv=none; d=google.com; s=arc-20160816; b=w3xttN1sbRIfgSYpgThJ9EOlOPAJO16gThCJjyCZOPHfbkIH6RsPYWh6rBDfhkeU+s 5gWFDdBQPVysloFbKD+W1awYMzYaJh4yJH6URXR4bEypAVObk7mMFGN2+LZv/a2skZgK R7V2gPB2dm5HlmE0Dzbm9R/4ZMaHVkDbfWPZkPVVpH3og5s9NI9JD+w4YtYyrbJMOsNx 0aa5K8QIp4KZuvGnNSzTK1sakfrzdnAJndhZNEoDV1VfD9LwSgWGkTb74jlhFduZsEPe 3JuiSBmXM0Y91tKMjchWqwRxQjjMm8WP+kd59pJtkYjVqKWcHO//qy0r+SU1Mhp5M5BC w84g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date; bh=v0uXK/Y7BtMLzyX+ZqLjY9tLRsDtA7zQpd5sYpKKvsk=; b=RTP1FDVZ2xTT1RBY9OEMSv/sI6wNoOEwfhFDxZ9PoFiQfWx5X0sBEP6Uq6uiiGmc0l lTdwqMAa1+tS7JrFZb2AOT58PT/Dy87Mj6NuEujlWsY1ZZITfL+nYsoc6HLi9kESM3/k UDpwwPslAJzdZYLh39K4LWXG8l2z1gai4m+UZEeSTTFxhYArHCi5OO9ffKVaXPOWDJmu nf3F3/ui8D4bdke94Sjxaub5R3N3JJNrdeFsImAVE9zBXUIMAzwCNabQpdBuWS7oe0uz hFDmKX275R7xCvoZh9U/ZhLAoRa5+HqvmU3t+0i+1dXKJbFmt0nV7HLxkCCmpDdWuFVb ewWQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p25si418340oto.168.2020.03.02.20.09.23; Mon, 02 Mar 2020 20:09:37 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727076AbgCCEIw (ORCPT + 99 others); Mon, 2 Mar 2020 23:08:52 -0500 Received: from mga04.intel.com ([192.55.52.120]:29628 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726990AbgCCEIw (ORCPT ); Mon, 2 Mar 2020 23:08:52 -0500 X-Amp-Result: UNKNOWN X-Amp-Original-Verdict: FILE UNKNOWN X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Mar 2020 20:08:51 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,510,1574150400"; d="scan'208";a="412600501" Received: from sjchrist-coffee.jf.intel.com (HELO linux.intel.com) ([10.54.74.202]) by orsmga005.jf.intel.com with ESMTP; 02 Mar 2020 20:08:51 -0800 Date: Mon, 2 Mar 2020 20:08:51 -0800 From: Sean Christopherson To: Xiaoyao Li Cc: Paolo Bonzini , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Jan Kiszka Subject: Re: [PATCH 1/6] KVM: x86: Fix tracing of CPUID.function when function is out-of-range Message-ID: <20200303040851.GD27842@linux.intel.com> References: <20200302195736.24777-1-sean.j.christopherson@intel.com> <20200302195736.24777-2-sean.j.christopherson@intel.com> <6b41fc5c-f7f4-b20d-cfb5-95bf13cc7534@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <6b41fc5c-f7f4-b20d-cfb5-95bf13cc7534@intel.com> User-Agent: Mutt/1.5.24 (2015-08-30) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Mar 03, 2020 at 10:50:03AM +0800, Xiaoyao Li wrote: > On 3/3/2020 3:57 AM, Sean Christopherson wrote: > >Rework kvm_cpuid() to query entry->function when adjusting the output > >values so that the original function (in the aptly named "function") is > >preserved for tracing. This fixes a bug where trace_kvm_cpuid() will > >trace the max function for a range instead of the requested function if > >the requested function is out-of-range and an entry for the max function > >exists. > > > >Fixes: 43561123ab37 ("kvm: x86: Improve emulation of CPUID leaves 0BH and 1FH") > >Reported-by: Jan Kiszka > >Cc: Jim Mattson > >Cc: Xiaoyao Li > >Signed-off-by: Sean Christopherson > >--- > > arch/x86/kvm/cpuid.c | 15 +++++++-------- > > 1 file changed, 7 insertions(+), 8 deletions(-) > > > >diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c > >index b1c469446b07..6be012937eba 100644 > >--- a/arch/x86/kvm/cpuid.c > >+++ b/arch/x86/kvm/cpuid.c > >@@ -997,12 +997,12 @@ static bool cpuid_function_in_range(struct kvm_vcpu *vcpu, u32 function) > > return max && function <= max->eax; > > } > >+/* Returns true if the requested leaf/function exists in guest CPUID. */ > > bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, > > u32 *ecx, u32 *edx, bool check_limit) > > { > >- u32 function = *eax, index = *ecx; > >+ const u32 function = *eax, index = *ecx; > > struct kvm_cpuid_entry2 *entry; > >- struct kvm_cpuid_entry2 *max; > > bool found; > > entry = kvm_find_cpuid_entry(vcpu, function, index); > >@@ -1015,18 +1015,17 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, > > */ > > if (!entry && check_limit && !guest_cpuid_is_amd(vcpu) && > > !cpuid_function_in_range(vcpu, function)) { > >- max = kvm_find_cpuid_entry(vcpu, 0, 0); > >- if (max) { > >- function = max->eax; > >- entry = kvm_find_cpuid_entry(vcpu, function, index); > >- } > >+ entry = kvm_find_cpuid_entry(vcpu, 0, 0); > >+ if (entry) > >+ entry = kvm_find_cpuid_entry(vcpu, entry->eax, index); > > There is a problem. > > when queried leaf is out of range on Intel CPU, it returns the maximum basic > leaf, and any dependence on input ECX (i.e., subleaf) value in the basic > leaf is honored. As disclaimed in SDM of CPUID instruction. That's what the code above does. > The ECX should be honored if and only the leaf has a significant index. > If the leaf doesn't has a significant index, it just ignores the EDX input s/EDX/ECX > in bare metal. > > So it should be something like: > > if (!entry && check_limit && !guest_cpuid_is_amd(vcpu) && > !cpuid_function_in_range(vcpu, function)) { > entry = kvm_find_cpuid_entry(vcpu, 0, 0); > if (entry) { > entry = kvm_find_cpuid_entry(vcpu, entry->eax, 0); > if (entry && > entry->flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX ) { This is unnecessary IMO. The only scenario where SIGNFICANT_INDEX is 0 and cpuid_entry(entry->eax, 0) != cpuid_entry(entry->eax, index) is if userspace created a cpuid entry for index>0 with SIGNFICANT_INDEX. That's a busted model, e.g. it'd be the SDM equivalent of an Intel CPU having different output for CPUID.0x16.0 and CPUID.16.5 despite the SDM stating that the CPUID.0x16 ignores the index. E.g. on my system with a max basic leaf of 0x16 $ cpuid -1 -r CPU: 0x00000000 0x00: eax=0x00000016 ebx=0x756e6547 ecx=0x6c65746e edx=0x49656e69 ... 0x00000016 0x00: eax=0x00000e74 ebx=0x0000125c ecx=0x00000064 edx=0x00000000 $ cpuid -1 -r -l 0x16 CPU: 0x00000016 0x00: eax=0x00000e74 ebx=0x0000125c ecx=0x00000064 edx=0x00000000 ~ $ cpuid -1 -r -l 0x16 -s 4 CPU: 0x00000016 0x04: eax=0x00000e74 ebx=0x0000125c ecx=0x00000064 edx=0x00000000 ~ $ cpuid -1 -r -l 0x16 -s 466 CPU: 0x00000016 0x1d2: eax=0x00000e74 ebx=0x0000125c ecx=0x00000064 edx=0x00000000 If it returned anything else for CPUID.0x16.0x4 then it'd be a CPU bug. Same thing here, it's a userspace bug if it creates a CPUID entry that shouldn't exist. E.g. ignoring Intel's silly "max basic leaf" behavior for the moment, if userspace created a entry for CPUID.0x0.N it would break the Linux kernel's cpu_detect(), as it doesn't initialize ECX when doing CPUID.0x0. > entry = kvm_find_cpuid_entry(vcpu, entry->eax, > index); > } > } > } > > > } > > if (entry) { > > *eax = entry->eax; > > *ebx = entry->ebx; > > *ecx = entry->ecx; > > *edx = entry->edx; > >- if (function == 7 && index == 0) { > >+ > >+ if (entry->function == 7 && index == 0) { > > u64 data; > > if (!__kvm_get_msr(vcpu, MSR_IA32_TSX_CTRL, &data, true) && > > (data & TSX_CTRL_CPUID_CLEAR)) > > >