Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S938843AbcKPKUJ (ORCPT ); Wed, 16 Nov 2016 05:20:09 -0500 Received: from terminus.zytor.com ([198.137.202.10]:60628 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752308AbcKPKUG (ORCPT ); Wed, 16 Nov 2016 05:20:06 -0500 Date: Wed, 16 Nov 2016 02:19:32 -0800 From: tip-bot for He Chen Message-ID: Cc: pbonzini@redhat.com, linux-kernel@vger.kernel.org, tglx@linutronix.de, bp@alien8.de, rkrcmar@redhat.com, mingo@kernel.org, hpa@zytor.com, luwei.kang@intel.com, he.chen@linux.intel.com, Piotr.Luc@intel.com, bp@suse.de Reply-To: bp@alien8.de, mingo@kernel.org, rkrcmar@redhat.com, tglx@linutronix.de, linux-kernel@vger.kernel.org, pbonzini@redhat.com, bp@suse.de, Piotr.Luc@intel.com, he.chen@linux.intel.com, hpa@zytor.com, luwei.kang@intel.com In-Reply-To: <1478856336-9388-3-git-send-email-he.chen@linux.intel.com> References: <1478856336-9388-3-git-send-email-he.chen@linux.intel.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/cpufeature] x86/cpuid: Provide get_scattered_cpuid_leaf() Git-Commit-ID: 47bdf3378d62a627cfb8a54e1180c08d67078b61 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4565 Lines: 121 Commit-ID: 47bdf3378d62a627cfb8a54e1180c08d67078b61 Gitweb: http://git.kernel.org/tip/47bdf3378d62a627cfb8a54e1180c08d67078b61 Author: He Chen AuthorDate: Fri, 11 Nov 2016 17:25:35 +0800 Committer: Thomas Gleixner CommitDate: Wed, 16 Nov 2016 11:13:09 +0100 x86/cpuid: Provide get_scattered_cpuid_leaf() Sparse populated CPUID leafs are collected in a software provided leaf to avoid bloat of the x86_capability array, but there is no way to rebuild the real leafs (e.g. for KVM CPUID enumeration) other than rereading the CPUID leaf from the CPU. While this is possible it is problematic as it does not take software disabled features into account. If a feature is disabled on the host it should not be exposed to a guest either. Add get_scattered_cpuid_leaf() which rebuilds the leaf from the scattered cpuid table information and the active CPU features. [ tglx: Rewrote changelog ] Signed-off-by: He Chen Reviewed-by: Borislav Petkov Cc: Luwei Kang Cc: kvm@vger.kernel.org Cc: Radim Krčmář Cc: Piotr Luc Cc: Borislav Petkov Cc: Paolo Bonzini Link: http://lkml.kernel.org/r/1478856336-9388-3-git-send-email-he.chen@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/processor.h | 3 +++ arch/x86/kernel/cpu/scattered.c | 49 ++++++++++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 8f6ac5b..e7f8c62 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -189,6 +189,9 @@ extern void identify_secondary_cpu(struct cpuinfo_x86 *); extern void print_cpu_info(struct cpuinfo_x86 *); void print_cpu_msr(struct cpuinfo_x86 *); extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c); +extern u32 get_scattered_cpuid_leaf(unsigned int level, + unsigned int sub_leaf, + enum cpuid_regs_idx reg); extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); extern void init_amd_cacheinfo(struct cpuinfo_x86 *c); diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index dbb470e..d1316f9 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -17,24 +17,25 @@ struct cpuid_bit { u32 sub_leaf; }; +/* Please keep the leaf sorted by cpuid_bit.level for faster search. */ +static const struct cpuid_bit cpuid_bits[] = { + { X86_FEATURE_APERFMPERF, CPUID_ECX, 0, 0x00000006, 0 }, + { X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 }, + { X86_FEATURE_INTEL_PT, CPUID_EBX, 25, 0x00000007, 0 }, + { X86_FEATURE_AVX512_4VNNIW, CPUID_EDX, 2, 0x00000007, 0 }, + { X86_FEATURE_AVX512_4FMAPS, CPUID_EDX, 3, 0x00000007, 0 }, + { X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 }, + { X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 }, + { X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 }, + { 0, 0, 0, 0, 0 } +}; + void init_scattered_cpuid_features(struct cpuinfo_x86 *c) { u32 max_level; u32 regs[4]; const struct cpuid_bit *cb; - static const struct cpuid_bit cpuid_bits[] = { - { X86_FEATURE_INTEL_PT, CPUID_EBX, 25, 0x00000007, 0 }, - { X86_FEATURE_AVX512_4VNNIW, CPUID_EDX, 2, 0x00000007, 0 }, - { X86_FEATURE_AVX512_4FMAPS, CPUID_EDX, 3, 0x00000007, 0 }, - { X86_FEATURE_APERFMPERF, CPUID_ECX, 0, 0x00000006, 0 }, - { X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 }, - { X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 }, - { X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 }, - { X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 }, - { 0, 0, 0, 0, 0 } - }; - for (cb = cpuid_bits; cb->feature; cb++) { /* Verify that the level is valid */ @@ -51,3 +52,27 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c) set_cpu_cap(c, cb->feature); } } + +u32 get_scattered_cpuid_leaf(unsigned int level, unsigned int sub_leaf, + enum cpuid_regs_idx reg) +{ + const struct cpuid_bit *cb; + u32 cpuid_val = 0; + + for (cb = cpuid_bits; cb->feature; cb++) { + + if (level > cb->level) + continue; + + if (level < cb->level) + break; + + if (reg == cb->reg && sub_leaf == cb->sub_leaf) { + if (cpu_has(&boot_cpu_data, cb->feature)) + cpuid_val |= BIT(cb->bit); + } + } + + return cpuid_val; +} +EXPORT_SYMBOL_GPL(get_scattered_cpuid_leaf);