From patchwork Thu Apr 22 00:56:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Koller X-Patchwork-Id: 12217255 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D65A8C43461 for ; Thu, 22 Apr 2021 00:56:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AD18760FE5 for ; Thu, 22 Apr 2021 00:56:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242027AbhDVA5O (ORCPT ); Wed, 21 Apr 2021 20:57:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54886 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240786AbhDVA5O (ORCPT ); Wed, 21 Apr 2021 20:57:14 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6808AC06138A for ; Wed, 21 Apr 2021 17:56:40 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id 59-20020a1709020241b02900e8de254a18so19151585plc.14 for ; Wed, 21 Apr 2021 17:56:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=XxDAh3fhzg5A8awaqIQozL0a7udxHE7UvhfJ/Wi4USQ=; b=OKzNJGs7evpkAgOjHMv/92KXILF1CXt1OoiqCa3/sFn+5Tiwyhbke+MVLj00a+QOQK W7Yrpe3/8/7w+6jmkjAWhZ6rim6es/ZqzjZjI5KtW92IgYhG/S4rtkcwxTm1jSctmdyw GzbCakasmyLuCDfYUgH5UCLR7gs8yvtx046Nv0VaRZ8TGXDSzFTNdbEDrqXAd9kUCK5u 3JpGsusiKCfOpONHLg+mTBNwbCBZDCKX8gTLxqATf9O+QOjjYM4jCAFt16kCO7GTKdT8 iEc7S5RdVChyd+fSHctUtWFA338V7T4HuaQ0p5zpR51sn6JCNbtXOzOMxUbOeWEXJwLQ z82g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=XxDAh3fhzg5A8awaqIQozL0a7udxHE7UvhfJ/Wi4USQ=; b=eqC4pA8OWAH2y7PrZgpnhDIKwmgOcjoMy0pU0F/N8Nj+vI+os7dOqVlwXM2z9v2NxP I+xQG67E9nZvkpnVuTYpA0cLM83c+otuqHJrZMxs5LnwzTu6619MzG7gtNEcNpiO2N1i mHbDae2cBLfa+SZGMY2m5srcyg4J9OHuRlwkRuD5g8KGJ3E1XANgvTSn4Rn/kFWkmHG3 HnTtNpFByjtTvQq6ipf/gdtdW3dB9wm5Y3rAe3xakm7xpxoCIH/LHkmWICJlv3lTz7Yw pGsJFjIOhsZgbuMulDRwRJGzAIAKLRyIUbM1Fj9viVk3BnyPqXr3LDCAWHqu3/fZ0Rrf 31UA== X-Gm-Message-State: AOAM533pviM0SJ6HhUfOuZ3oucLXamLRT0ziru4C1MQtZtWuIWO+NmIl Y2Pi0knVWKh0/zhdXBLiqPCr/tSG44Zlxw== X-Google-Smtp-Source: ABdhPJytWStGBaql7sF4DNf3GoW+tjXcAJaAsgYk0ZcCMM/ByrNRJa463UMEIpmgYtWq8wO9TgWiGOhfc+BiQA== X-Received: from ricarkol2.c.googlers.com ([fda3:e722:ac3:10:24:72f4:c0a8:62fe]) (user=ricarkol job=sendgmr) by 2002:aa7:87d5:0:b029:25a:b5f8:15ab with SMTP id i21-20020aa787d50000b029025ab5f815abmr861328pfo.22.1619052999831; Wed, 21 Apr 2021 17:56:39 -0700 (PDT) Date: Wed, 21 Apr 2021 17:56:22 -0700 In-Reply-To: <20210422005626.564163-1-ricarkol@google.com> Message-Id: <20210422005626.564163-2-ricarkol@google.com> Mime-Version: 1.0 References: <20210422005626.564163-1-ricarkol@google.com> X-Mailer: git-send-email 2.31.1.368.gbe11c130af-goog Subject: [PATCH 1/5] KVM: x86: Move reverse CPUID helpers to separate header file From: Ricardo Koller To: Paolo Bonzini Cc: kvm@vger.kernel.org, Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , "H. Peter Anvin" , Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , Nathan Chancellor , Nick Desaulniers , linux-kernel@vger.kernel.org, clang-built-linux@googlegroups.com, Ricardo Koller Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Split out the reverse CPUID machinery to a dedicated header file so that KVM selftests can reuse the reverse CPUID definitions without introducing any '#ifdef __KERNEL__' pollution. Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Ricardo Koller --- arch/x86/kvm/cpuid.h | 177 +-------------------------------- arch/x86/kvm/reverse_cpuid.h | 185 +++++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+), 176 deletions(-) create mode 100644 arch/x86/kvm/reverse_cpuid.h diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index 888e88b42e8d..6132ed3c6ebf 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -3,28 +3,11 @@ #define ARCH_X86_KVM_CPUID_H #include "x86.h" +#include "reverse_cpuid.h" #include #include #include -/* - * Hardware-defined CPUID leafs that are scattered in the kernel, but need to - * be directly used by KVM. Note, these word values conflict with the kernel's - * "bug" caps, but KVM doesn't use those. - */ -enum kvm_only_cpuid_leafs { - CPUID_12_EAX = NCAPINTS, - NR_KVM_CPU_CAPS, - - NKVMCAPINTS = NR_KVM_CPU_CAPS - NCAPINTS, -}; - -#define KVM_X86_FEATURE(w, f) ((w)*32 + (f)) - -/* Intel-defined SGX sub-features, CPUID level 0x12 (EAX). */ -#define KVM_X86_FEATURE_SGX1 KVM_X86_FEATURE(CPUID_12_EAX, 0) -#define KVM_X86_FEATURE_SGX2 KVM_X86_FEATURE(CPUID_12_EAX, 1) - extern u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly; void kvm_set_cpu_caps(void); @@ -76,164 +59,6 @@ static inline bool page_address_valid(struct kvm_vcpu *vcpu, gpa_t gpa) return kvm_vcpu_is_legal_aligned_gpa(vcpu, gpa, PAGE_SIZE); } -struct cpuid_reg { - u32 function; - u32 index; - int reg; -}; - -static const struct cpuid_reg reverse_cpuid[] = { - [CPUID_1_EDX] = { 1, 0, CPUID_EDX}, - [CPUID_8000_0001_EDX] = {0x80000001, 0, CPUID_EDX}, - [CPUID_8086_0001_EDX] = {0x80860001, 0, CPUID_EDX}, - [CPUID_1_ECX] = { 1, 0, CPUID_ECX}, - [CPUID_C000_0001_EDX] = {0xc0000001, 0, CPUID_EDX}, - [CPUID_8000_0001_ECX] = {0x80000001, 0, CPUID_ECX}, - [CPUID_7_0_EBX] = { 7, 0, CPUID_EBX}, - [CPUID_D_1_EAX] = { 0xd, 1, CPUID_EAX}, - [CPUID_8000_0008_EBX] = {0x80000008, 0, CPUID_EBX}, - [CPUID_6_EAX] = { 6, 0, CPUID_EAX}, - [CPUID_8000_000A_EDX] = {0x8000000a, 0, CPUID_EDX}, - [CPUID_7_ECX] = { 7, 0, CPUID_ECX}, - [CPUID_8000_0007_EBX] = {0x80000007, 0, CPUID_EBX}, - [CPUID_7_EDX] = { 7, 0, CPUID_EDX}, - [CPUID_7_1_EAX] = { 7, 1, CPUID_EAX}, - [CPUID_12_EAX] = {0x00000012, 0, CPUID_EAX}, -}; - -/* - * Reverse CPUID and its derivatives can only be used for hardware-defined - * feature words, i.e. words whose bits directly correspond to a CPUID leaf. - * Retrieving a feature bit or masking guest CPUID from a Linux-defined word - * is nonsensical as the bit number/mask is an arbitrary software-defined value - * and can't be used by KVM to query/control guest capabilities. And obviously - * the leaf being queried must have an entry in the lookup table. - */ -static __always_inline void reverse_cpuid_check(unsigned int x86_leaf) -{ - BUILD_BUG_ON(x86_leaf == CPUID_LNX_1); - BUILD_BUG_ON(x86_leaf == CPUID_LNX_2); - BUILD_BUG_ON(x86_leaf == CPUID_LNX_3); - BUILD_BUG_ON(x86_leaf == CPUID_LNX_4); - BUILD_BUG_ON(x86_leaf >= ARRAY_SIZE(reverse_cpuid)); - BUILD_BUG_ON(reverse_cpuid[x86_leaf].function == 0); -} - -/* - * Translate feature bits that are scattered in the kernel's cpufeatures word - * into KVM feature words that align with hardware's definitions. - */ -static __always_inline u32 __feature_translate(int x86_feature) -{ - if (x86_feature == X86_FEATURE_SGX1) - return KVM_X86_FEATURE_SGX1; - else if (x86_feature == X86_FEATURE_SGX2) - return KVM_X86_FEATURE_SGX2; - - return x86_feature; -} - -static __always_inline u32 __feature_leaf(int x86_feature) -{ - return __feature_translate(x86_feature) / 32; -} - -/* - * Retrieve the bit mask from an X86_FEATURE_* definition. Features contain - * the hardware defined bit number (stored in bits 4:0) and a software defined - * "word" (stored in bits 31:5). The word is used to index into arrays of - * bit masks that hold the per-cpu feature capabilities, e.g. this_cpu_has(). - */ -static __always_inline u32 __feature_bit(int x86_feature) -{ - x86_feature = __feature_translate(x86_feature); - - reverse_cpuid_check(x86_feature / 32); - return 1 << (x86_feature & 31); -} - -#define feature_bit(name) __feature_bit(X86_FEATURE_##name) - -static __always_inline struct cpuid_reg x86_feature_cpuid(unsigned int x86_feature) -{ - unsigned int x86_leaf = __feature_leaf(x86_feature); - - reverse_cpuid_check(x86_leaf); - return reverse_cpuid[x86_leaf]; -} - -static __always_inline u32 *__cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, - u32 reg) -{ - switch (reg) { - case CPUID_EAX: - return &entry->eax; - case CPUID_EBX: - return &entry->ebx; - case CPUID_ECX: - return &entry->ecx; - case CPUID_EDX: - return &entry->edx; - default: - BUILD_BUG(); - return NULL; - } -} - -static __always_inline u32 *cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, - unsigned int x86_feature) -{ - const struct cpuid_reg cpuid = x86_feature_cpuid(x86_feature); - - return __cpuid_entry_get_reg(entry, cpuid.reg); -} - -static __always_inline u32 cpuid_entry_get(struct kvm_cpuid_entry2 *entry, - unsigned int x86_feature) -{ - u32 *reg = cpuid_entry_get_reg(entry, x86_feature); - - return *reg & __feature_bit(x86_feature); -} - -static __always_inline bool cpuid_entry_has(struct kvm_cpuid_entry2 *entry, - unsigned int x86_feature) -{ - return cpuid_entry_get(entry, x86_feature); -} - -static __always_inline void cpuid_entry_clear(struct kvm_cpuid_entry2 *entry, - unsigned int x86_feature) -{ - u32 *reg = cpuid_entry_get_reg(entry, x86_feature); - - *reg &= ~__feature_bit(x86_feature); -} - -static __always_inline void cpuid_entry_set(struct kvm_cpuid_entry2 *entry, - unsigned int x86_feature) -{ - u32 *reg = cpuid_entry_get_reg(entry, x86_feature); - - *reg |= __feature_bit(x86_feature); -} - -static __always_inline void cpuid_entry_change(struct kvm_cpuid_entry2 *entry, - unsigned int x86_feature, - bool set) -{ - u32 *reg = cpuid_entry_get_reg(entry, x86_feature); - - /* - * Open coded instead of using cpuid_entry_{clear,set}() to coerce the - * compiler into using CMOV instead of Jcc when possible. - */ - if (set) - *reg |= __feature_bit(x86_feature); - else - *reg &= ~__feature_bit(x86_feature); -} - static __always_inline void cpuid_entry_override(struct kvm_cpuid_entry2 *entry, enum cpuid_leafs leaf) { diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h new file mode 100644 index 000000000000..8e0756ddab1a --- /dev/null +++ b/arch/x86/kvm/reverse_cpuid.h @@ -0,0 +1,185 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef ARCH_X86_KVM_REVERSE_CPUID_H +#define ARCH_X86_KVM_REVERSE_CPUID_H + +#include +#include +#include + +/* + * Hardware-defined CPUID leafs that are scattered in the kernel, but need to + * be directly used by KVM. Note, these word values conflict with the kernel's + * "bug" caps, but KVM doesn't use those. + */ +enum kvm_only_cpuid_leafs { + CPUID_12_EAX = NCAPINTS, + NR_KVM_CPU_CAPS, + + NKVMCAPINTS = NR_KVM_CPU_CAPS - NCAPINTS, +}; + +#define KVM_X86_FEATURE(w, f) ((w)*32 + (f)) + +/* Intel-defined SGX sub-features, CPUID level 0x12 (EAX). */ +#define KVM_X86_FEATURE_SGX1 KVM_X86_FEATURE(CPUID_12_EAX, 0) +#define KVM_X86_FEATURE_SGX2 KVM_X86_FEATURE(CPUID_12_EAX, 1) + +struct cpuid_reg { + u32 function; + u32 index; + int reg; +}; + +static const struct cpuid_reg reverse_cpuid[] = { + [CPUID_1_EDX] = { 1, 0, CPUID_EDX}, + [CPUID_8000_0001_EDX] = {0x80000001, 0, CPUID_EDX}, + [CPUID_8086_0001_EDX] = {0x80860001, 0, CPUID_EDX}, + [CPUID_1_ECX] = { 1, 0, CPUID_ECX}, + [CPUID_C000_0001_EDX] = {0xc0000001, 0, CPUID_EDX}, + [CPUID_8000_0001_ECX] = {0x80000001, 0, CPUID_ECX}, + [CPUID_7_0_EBX] = { 7, 0, CPUID_EBX}, + [CPUID_D_1_EAX] = { 0xd, 1, CPUID_EAX}, + [CPUID_8000_0008_EBX] = {0x80000008, 0, CPUID_EBX}, + [CPUID_6_EAX] = { 6, 0, CPUID_EAX}, + [CPUID_8000_000A_EDX] = {0x8000000a, 0, CPUID_EDX}, + [CPUID_7_ECX] = { 7, 0, CPUID_ECX}, + [CPUID_8000_0007_EBX] = {0x80000007, 0, CPUID_EBX}, + [CPUID_7_EDX] = { 7, 0, CPUID_EDX}, + [CPUID_7_1_EAX] = { 7, 1, CPUID_EAX}, + [CPUID_12_EAX] = {0x00000012, 0, CPUID_EAX}, +}; + +/* + * Reverse CPUID and its derivatives can only be used for hardware-defined + * feature words, i.e. words whose bits directly correspond to a CPUID leaf. + * Retrieving a feature bit or masking guest CPUID from a Linux-defined word + * is nonsensical as the bit number/mask is an arbitrary software-defined value + * and can't be used by KVM to query/control guest capabilities. And obviously + * the leaf being queried must have an entry in the lookup table. + */ +static __always_inline void reverse_cpuid_check(unsigned int x86_leaf) +{ + BUILD_BUG_ON(x86_leaf == CPUID_LNX_1); + BUILD_BUG_ON(x86_leaf == CPUID_LNX_2); + BUILD_BUG_ON(x86_leaf == CPUID_LNX_3); + BUILD_BUG_ON(x86_leaf == CPUID_LNX_4); + BUILD_BUG_ON(x86_leaf >= ARRAY_SIZE(reverse_cpuid)); + BUILD_BUG_ON(reverse_cpuid[x86_leaf].function == 0); +} + +/* + * Translate feature bits that are scattered in the kernel's cpufeatures word + * into KVM feature words that align with hardware's definitions. + */ +static __always_inline u32 __feature_translate(int x86_feature) +{ + if (x86_feature == X86_FEATURE_SGX1) + return KVM_X86_FEATURE_SGX1; + else if (x86_feature == X86_FEATURE_SGX2) + return KVM_X86_FEATURE_SGX2; + + return x86_feature; +} + +static __always_inline u32 __feature_leaf(int x86_feature) +{ + return __feature_translate(x86_feature) / 32; +} + +/* + * Retrieve the bit mask from an X86_FEATURE_* definition. Features contain + * the hardware defined bit number (stored in bits 4:0) and a software defined + * "word" (stored in bits 31:5). The word is used to index into arrays of + * bit masks that hold the per-cpu feature capabilities, e.g. this_cpu_has(). + */ +static __always_inline u32 __feature_bit(int x86_feature) +{ + x86_feature = __feature_translate(x86_feature); + + reverse_cpuid_check(x86_feature / 32); + return 1 << (x86_feature & 31); +} + +#define feature_bit(name) __feature_bit(X86_FEATURE_##name) + +static __always_inline struct cpuid_reg x86_feature_cpuid(unsigned int x86_feature) +{ + unsigned int x86_leaf = __feature_leaf(x86_feature); + + reverse_cpuid_check(x86_leaf); + return reverse_cpuid[x86_leaf]; +} + +static __always_inline u32 *__cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, + u32 reg) +{ + switch (reg) { + case CPUID_EAX: + return &entry->eax; + case CPUID_EBX: + return &entry->ebx; + case CPUID_ECX: + return &entry->ecx; + case CPUID_EDX: + return &entry->edx; + default: + BUILD_BUG(); + return NULL; + } +} + +static __always_inline u32 *cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, + unsigned int x86_feature) +{ + const struct cpuid_reg cpuid = x86_feature_cpuid(x86_feature); + + return __cpuid_entry_get_reg(entry, cpuid.reg); +} + +static __always_inline u32 cpuid_entry_get(struct kvm_cpuid_entry2 *entry, + unsigned int x86_feature) +{ + u32 *reg = cpuid_entry_get_reg(entry, x86_feature); + + return *reg & __feature_bit(x86_feature); +} + +static __always_inline bool cpuid_entry_has(struct kvm_cpuid_entry2 *entry, + unsigned int x86_feature) +{ + return cpuid_entry_get(entry, x86_feature); +} + +static __always_inline void cpuid_entry_clear(struct kvm_cpuid_entry2 *entry, + unsigned int x86_feature) +{ + u32 *reg = cpuid_entry_get_reg(entry, x86_feature); + + *reg &= ~__feature_bit(x86_feature); +} + +static __always_inline void cpuid_entry_set(struct kvm_cpuid_entry2 *entry, + unsigned int x86_feature) +{ + u32 *reg = cpuid_entry_get_reg(entry, x86_feature); + + *reg |= __feature_bit(x86_feature); +} + +static __always_inline void cpuid_entry_change(struct kvm_cpuid_entry2 *entry, + unsigned int x86_feature, + bool set) +{ + u32 *reg = cpuid_entry_get_reg(entry, x86_feature); + + /* + * Open coded instead of using cpuid_entry_{clear,set}() to coerce the + * compiler into using CMOV instead of Jcc when possible. + */ + if (set) + *reg |= __feature_bit(x86_feature); + else + *reg &= ~__feature_bit(x86_feature); +} + +#endif /* ARCH_X86_KVM_REVERSE_CPUID_H */ From patchwork Thu Apr 22 00:56:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Koller X-Patchwork-Id: 12217257 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 93D8DC433B4 for ; Thu, 22 Apr 2021 00:56:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6704261428 for ; Thu, 22 Apr 2021 00:56:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242619AbhDVA5S (ORCPT ); Wed, 21 Apr 2021 20:57:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54896 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242419AbhDVA5Q (ORCPT ); Wed, 21 Apr 2021 20:57:16 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 739F6C06174A for ; Wed, 21 Apr 2021 17:56:42 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id e8-20020a2587480000b02904e5857564e2so17992114ybn.16 for ; Wed, 21 Apr 2021 17:56:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=nQ/zpK/kz603934NoaeU4Gk/eDpKeLkLBX1Q9YclUPA=; b=eP0O7z+LQB2aToODGjmklTU4/ZEqYkoE5cnDIg2lo7Q+vpJ9bR12OhCB4CdXqay1zU 77yav77ko4Ygni13AIZ16v+K0y/18AcUBfAuRlm+kSdBvwI6G6MIqX5wJvPWr1vjpjOT RY8cp2nkuurYbZjYKn1mnbrj8FVF5olWJPGwy2dCCUeMAY5P/AC+h6GTyXluGrb70v6R x49xRasTZeVZhhIpM4E8MDgPWfehTjBizf1sIKQb41Tlqee3lYIoFIBzemfr1TeLQ35q 4XTfr+dmAHno0tDXFgncMkcFOZrVGxqV/7CWSSPqfwqqyUFZzQgP2L4eIhcLZJxQbFBz 8X+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=nQ/zpK/kz603934NoaeU4Gk/eDpKeLkLBX1Q9YclUPA=; b=ZmOnid83X1brkj86tZBJTEb4TDrcv+7IR5OwVFDEIXFVJ5ii2j+Nxqn3ZjMNNeAoqe h6nzZPo70YZ3xs0D7aGm+et6U+dIjevL/5t990q8xydhjLQhjNHEBYYws8sD6UBQ5JzY KxMRcEvnGfGW59czv+7aUroN/Bp056I/2WJm0SBZUhNfUhvsYhIQk9mwCcMOuuigaDvU bTCdAMowLKlIn7eNGMbktBdQxp1SSyJwLAZ35gcwyrdMywPPfNbtmYs6JWlwOh1f+65c T2obdJVFALvL7iPMZUud8PmcFt1F2SHcEPghrhONP84TS/A02DJcf1N1EZSV7AZJ+WNx 8nOA== X-Gm-Message-State: AOAM5322k9+OXWnx9Jjym3uOW5tl7rsFe25Uhge5TVTNxNVlqh4WNGP6 ee73iQUo/MLfTR1nZEMur/2XZUzppgtkZw== X-Google-Smtp-Source: ABdhPJwRNsexrlF6Et7Tudrdqp8qhO7el0jKsQTvh4PiuQzg//HU3EEJk0WGdQkuBV0VKD9bmeLOfOp/jgfbcg== X-Received: from ricarkol2.c.googlers.com ([fda3:e722:ac3:10:24:72f4:c0a8:62fe]) (user=ricarkol job=sendgmr) by 2002:a25:b9c1:: with SMTP id y1mr979521ybj.321.1619053001722; Wed, 21 Apr 2021 17:56:41 -0700 (PDT) Date: Wed, 21 Apr 2021 17:56:23 -0700 In-Reply-To: <20210422005626.564163-1-ricarkol@google.com> Message-Id: <20210422005626.564163-3-ricarkol@google.com> Mime-Version: 1.0 References: <20210422005626.564163-1-ricarkol@google.com> X-Mailer: git-send-email 2.31.1.368.gbe11c130af-goog Subject: [PATCH 2/5] x86/cpu: Expose CPUID regs, leaf and index definitions to tools From: Ricardo Koller To: Paolo Bonzini Cc: kvm@vger.kernel.org, Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , "H. Peter Anvin" , Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , Nathan Chancellor , Nick Desaulniers , linux-kernel@vger.kernel.org, clang-built-linux@googlegroups.com, Ricardo Koller Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Move cpuid_regs, cpuid_regs_idx, and cpuid_leafs out of their '#ifdef __KERNEL__' guards so that KVM selftests can reuse the definitions in future patches. Move cpuid_regs and cpuid_regs_idx from processor.h to cpufeature.h to avoid blasting processor.h with several '#ifdefs'. Suggested-by: Sean Christopherson Signed-off-by: Ricardo Koller --- arch/x86/events/intel/pt.c | 1 + arch/x86/include/asm/cpufeature.h | 23 ++++++++++++++++++----- arch/x86/include/asm/processor.h | 11 ----------- arch/x86/kernel/cpu/scattered.c | 2 +- arch/x86/kernel/cpuid.c | 2 +- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c index e94af4a54d0d..882b1478556e 100644 --- a/arch/x86/events/intel/pt.c +++ b/arch/x86/events/intel/pt.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "../perf_event.h" #include "pt.h" diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 1728d4ce5730..22458ab5aac4 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -2,12 +2,19 @@ #ifndef _ASM_X86_CPUFEATURE_H #define _ASM_X86_CPUFEATURE_H -#include +#include -#if defined(__KERNEL__) && !defined(__ASSEMBLY__) +#ifndef __ASSEMBLY__ +struct cpuid_regs { + u32 eax, ebx, ecx, edx; +}; -#include -#include +enum cpuid_regs_idx { + CPUID_EAX = 0, + CPUID_EBX, + CPUID_ECX, + CPUID_EDX, +}; enum cpuid_leafs { @@ -32,6 +39,11 @@ enum cpuid_leafs CPUID_7_EDX, CPUID_8000_001F_EAX, }; +#ifdef __KERNEL__ + +#include +#include +#include #ifdef CONFIG_X86_FEATURE_NAMES extern const char * const x86_cap_flags[NCAPINTS*32]; @@ -240,5 +252,6 @@ static __always_inline bool _static_cpu_has(u16 bit) #define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \ boot_cpu_data.x86_model -#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */ +#endif /* defined(__KERNEL__) */ +#endif /* !defined(__ASSEMBLY__) */ #endif /* _ASM_X86_CPUFEATURE_H */ diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index dc6d149bf851..bc7fa3de7ccc 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -142,17 +142,6 @@ struct cpuinfo_x86 { unsigned initialized : 1; } __randomize_layout; -struct cpuid_regs { - u32 eax, ebx, ecx, edx; -}; - -enum cpuid_regs_idx { - CPUID_EAX = 0, - CPUID_EBX, - CPUID_ECX, - CPUID_EDX, -}; - #define X86_VENDOR_INTEL 0 #define X86_VENDOR_CYRIX 1 #define X86_VENDOR_AMD 2 diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index 21d1f062895a..bcbcda1e329b 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include "cpu.h" diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 6f7b8cc1bc9f..23e67220445b 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -37,7 +37,7 @@ #include #include -#include +#include #include static struct class *cpuid_class; From patchwork Thu Apr 22 00:56:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Koller X-Patchwork-Id: 12217259 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 24249C43460 for ; Thu, 22 Apr 2021 00:56:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 055F661430 for ; Thu, 22 Apr 2021 00:56:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244303AbhDVA5U (ORCPT ); Wed, 21 Apr 2021 20:57:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54914 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243387AbhDVA5S (ORCPT ); Wed, 21 Apr 2021 20:57:18 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0C16BC06174A for ; Wed, 21 Apr 2021 17:56:44 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id cu23-20020a17090afa97b0290152471ab665so957758pjb.8 for ; Wed, 21 Apr 2021 17:56:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=F1YIESlA0/i8trOgg7KpVXZp0asbzYmi0IVBmNPCtJs=; b=OD6htb2yTD0u/MM9HZBQBUu4BFLRXbmrrUmNnx8Kb6ffq8IFdnhAP8Lq8zgQ9ovBxD MozMJVlC0WxIZ8BP97ezSTTiZi7dVCh+9M7MbTqq0BqdIhl7ge+yXTDdpKBcazFDeqzS iS7YuUWGEOPNkFaLbKhiZFE85iBouNRmk2LSg86p4yQx3i6g5fFDoN6eyuk5G5pMtCzz 96+D2aI8ku1/Edq7WLpW/dnq+/s/IyRgNudREvgbtZB8FUx+CTjCMOazAQzJmHGT6PAV 0pifOH0bbAWkdwGFkvA7ivNY9eG1UjeyWIbFE1chaLPGCNxSz5UmIKPlyO/s0Y7LmlSO wV8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=F1YIESlA0/i8trOgg7KpVXZp0asbzYmi0IVBmNPCtJs=; b=R8UKrp4plwEno8DejbLIkd77d9tA5ZO1Kvx8n2eemluSL+0YtAGPYXoGGT1btlzHnM PLQfOkhia3ySFLj3FXsdDwDQIJSYjSM8TsrOV4Cx0OLw3y4ubo2JdHIC83J73QWGQxAN iaffYuGCKMEzyjY3/jZ5QBMqtStgavcnB4HbEp5n8iogIn8ktI9Pf69yCm2fngwYErmY NS4vl+1f5qj4QKl1L7s1Hyg6sqZpLqU/L3q6/9DdS93cvoGkEmaHfxWwbOQ6Q9usXVAC oGYq2rD6+jDSKb7v0MMvT26AKfQAjNuyMJUdl0Fzjv1PUnOFHjWvA9p685dHC2M3alpN gUhA== X-Gm-Message-State: AOAM5326Pk9YG0198JNKn0XXfCwMCicSXQh6ch/W5BKxmyPD41O6WbIA 2+aD1f/vNljfWPvNZ/IbElNoFQhhAZuvBQ== X-Google-Smtp-Source: ABdhPJxzUU0cXov3Pd8egAv3XvAhn3YUjZSNNf0UyLo9cXG0zTY1+EiUw8ypuAwO6dsv0jSMhuxRauafY5pmGQ== X-Received: from ricarkol2.c.googlers.com ([fda3:e722:ac3:10:24:72f4:c0a8:62fe]) (user=ricarkol job=sendgmr) by 2002:a63:fc10:: with SMTP id j16mr862526pgi.152.1619053003433; Wed, 21 Apr 2021 17:56:43 -0700 (PDT) Date: Wed, 21 Apr 2021 17:56:24 -0700 In-Reply-To: <20210422005626.564163-1-ricarkol@google.com> Message-Id: <20210422005626.564163-4-ricarkol@google.com> Mime-Version: 1.0 References: <20210422005626.564163-1-ricarkol@google.com> X-Mailer: git-send-email 2.31.1.368.gbe11c130af-goog Subject: [PATCH 3/5] tools headers x86: Copy cpuid helpers from the kernel From: Ricardo Koller To: Paolo Bonzini Cc: kvm@vger.kernel.org, Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , "H. Peter Anvin" , Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , Nathan Chancellor , Nick Desaulniers , linux-kernel@vger.kernel.org, clang-built-linux@googlegroups.com, Ricardo Koller Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Copy arch/x86/include/asm/acpufeature.h and arch/x86/kvm/reverse_cpuid.h from the kernel so that KVM selftests can use them in the next commits. Also update the tools copy of arch/x86/include/asm/acpufeatures.h. cpufeature.h is copied into tools/arch/x86/include like most other headers. reverse_cpuid.h is a special case as it's copied into the KVM selftests include location: tools/testing/selftests/kvm/include/x86_64/. These should be kept in sync, ideally with the help of some script like check-headers.sh used by tools/perf/. Signed-off-by: Ricardo Koller --- tools/arch/x86/include/asm/cpufeature.h | 257 ++++++++++++++++++ tools/arch/x86/include/asm/cpufeatures.h | 3 + .../kvm/include/x86_64/reverse_cpuid.h | 185 +++++++++++++ 3 files changed, 445 insertions(+) create mode 100644 tools/arch/x86/include/asm/cpufeature.h create mode 100644 tools/testing/selftests/kvm/include/x86_64/reverse_cpuid.h diff --git a/tools/arch/x86/include/asm/cpufeature.h b/tools/arch/x86/include/asm/cpufeature.h new file mode 100644 index 000000000000..22458ab5aac4 --- /dev/null +++ b/tools/arch/x86/include/asm/cpufeature.h @@ -0,0 +1,257 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_CPUFEATURE_H +#define _ASM_X86_CPUFEATURE_H + +#include + +#ifndef __ASSEMBLY__ +struct cpuid_regs { + u32 eax, ebx, ecx, edx; +}; + +enum cpuid_regs_idx { + CPUID_EAX = 0, + CPUID_EBX, + CPUID_ECX, + CPUID_EDX, +}; + +enum cpuid_leafs +{ + CPUID_1_EDX = 0, + CPUID_8000_0001_EDX, + CPUID_8086_0001_EDX, + CPUID_LNX_1, + CPUID_1_ECX, + CPUID_C000_0001_EDX, + CPUID_8000_0001_ECX, + CPUID_LNX_2, + CPUID_LNX_3, + CPUID_7_0_EBX, + CPUID_D_1_EAX, + CPUID_LNX_4, + CPUID_7_1_EAX, + CPUID_8000_0008_EBX, + CPUID_6_EAX, + CPUID_8000_000A_EDX, + CPUID_7_ECX, + CPUID_8000_0007_EBX, + CPUID_7_EDX, + CPUID_8000_001F_EAX, +}; +#ifdef __KERNEL__ + +#include +#include +#include + +#ifdef CONFIG_X86_FEATURE_NAMES +extern const char * const x86_cap_flags[NCAPINTS*32]; +extern const char * const x86_power_flags[32]; +#define X86_CAP_FMT "%s" +#define x86_cap_flag(flag) x86_cap_flags[flag] +#else +#define X86_CAP_FMT "%d:%d" +#define x86_cap_flag(flag) ((flag) >> 5), ((flag) & 31) +#endif + +/* + * In order to save room, we index into this array by doing + * X86_BUG_ - NCAPINTS*32. + */ +extern const char * const x86_bug_flags[NBUGINTS*32]; + +#define test_cpu_cap(c, bit) \ + test_bit(bit, (unsigned long *)((c)->x86_capability)) + +/* + * There are 32 bits/features in each mask word. The high bits + * (selected with (bit>>5) give us the word number and the low 5 + * bits give us the bit/feature number inside the word. + * (1UL<<((bit)&31) gives us a mask for the feature_bit so we can + * see if it is set in the mask word. + */ +#define CHECK_BIT_IN_MASK_WORD(maskname, word, bit) \ + (((bit)>>5)==(word) && (1UL<<((bit)&31) & maskname##word )) + +/* + * {REQUIRED,DISABLED}_MASK_CHECK below may seem duplicated with the + * following BUILD_BUG_ON_ZERO() check but when NCAPINTS gets changed, all + * header macros which use NCAPINTS need to be changed. The duplicated macro + * use causes the compiler to issue errors for all headers so that all usage + * sites can be corrected. + */ +#define REQUIRED_MASK_BIT_SET(feature_bit) \ + ( CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 0, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 1, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 2, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 3, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 4, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 5, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 6, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 7, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 8, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 9, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 10, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 11, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 12, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 13, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 14, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 15, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 16, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 17, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 18, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 19, feature_bit) || \ + REQUIRED_MASK_CHECK || \ + BUILD_BUG_ON_ZERO(NCAPINTS != 20)) + +#define DISABLED_MASK_BIT_SET(feature_bit) \ + ( CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 0, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 1, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 2, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 3, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 4, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 5, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 6, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 7, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 8, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 9, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 10, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 11, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 12, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 13, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 14, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 15, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 16, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 17, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 18, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 19, feature_bit) || \ + DISABLED_MASK_CHECK || \ + BUILD_BUG_ON_ZERO(NCAPINTS != 20)) + +#define cpu_has(c, bit) \ + (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \ + test_cpu_cap(c, bit)) + +#define this_cpu_has(bit) \ + (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \ + x86_this_cpu_test_bit(bit, \ + (unsigned long __percpu *)&cpu_info.x86_capability)) + +/* + * This macro is for detection of features which need kernel + * infrastructure to be used. It may *not* directly test the CPU + * itself. Use the cpu_has() family if you want true runtime + * testing of CPU features, like in hypervisor code where you are + * supporting a possible guest feature where host support for it + * is not relevant. + */ +#define cpu_feature_enabled(bit) \ + (__builtin_constant_p(bit) && DISABLED_MASK_BIT_SET(bit) ? 0 : static_cpu_has(bit)) + +#define boot_cpu_has(bit) cpu_has(&boot_cpu_data, bit) + +#define set_cpu_cap(c, bit) set_bit(bit, (unsigned long *)((c)->x86_capability)) + +extern void setup_clear_cpu_cap(unsigned int bit); +extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit); + +#define setup_force_cpu_cap(bit) do { \ + set_cpu_cap(&boot_cpu_data, bit); \ + set_bit(bit, (unsigned long *)cpu_caps_set); \ +} while (0) + +#define setup_force_cpu_bug(bit) setup_force_cpu_cap(bit) + +#if defined(__clang__) && !defined(CONFIG_CC_HAS_ASM_GOTO) + +/* + * Workaround for the sake of BPF compilation which utilizes kernel + * headers, but clang does not support ASM GOTO and fails the build. + */ +#ifndef __BPF_TRACING__ +#warning "Compiler lacks ASM_GOTO support. Add -D __BPF_TRACING__ to your compiler arguments" +#endif + +#define static_cpu_has(bit) boot_cpu_has(bit) + +#else + +/* + * Static testing of CPU features. Used the same as boot_cpu_has(). It + * statically patches the target code for additional performance. Use + * static_cpu_has() only in fast paths, where every cycle counts. Which + * means that the boot_cpu_has() variant is already fast enough for the + * majority of cases and you should stick to using it as it is generally + * only two instructions: a RIP-relative MOV and a TEST. + */ +static __always_inline bool _static_cpu_has(u16 bit) +{ + asm_volatile_goto("1: jmp 6f\n" + "2:\n" + ".skip -(((5f-4f) - (2b-1b)) > 0) * " + "((5f-4f) - (2b-1b)),0x90\n" + "3:\n" + ".section .altinstructions,\"a\"\n" + " .long 1b - .\n" /* src offset */ + " .long 4f - .\n" /* repl offset */ + " .word %P[always]\n" /* always replace */ + " .byte 3b - 1b\n" /* src len */ + " .byte 5f - 4f\n" /* repl len */ + " .byte 3b - 2b\n" /* pad len */ + ".previous\n" + ".section .altinstr_replacement,\"ax\"\n" + "4: jmp %l[t_no]\n" + "5:\n" + ".previous\n" + ".section .altinstructions,\"a\"\n" + " .long 1b - .\n" /* src offset */ + " .long 0\n" /* no replacement */ + " .word %P[feature]\n" /* feature bit */ + " .byte 3b - 1b\n" /* src len */ + " .byte 0\n" /* repl len */ + " .byte 0\n" /* pad len */ + ".previous\n" + ".section .altinstr_aux,\"ax\"\n" + "6:\n" + " testb %[bitnum],%[cap_byte]\n" + " jnz %l[t_yes]\n" + " jmp %l[t_no]\n" + ".previous\n" + : : [feature] "i" (bit), + [always] "i" (X86_FEATURE_ALWAYS), + [bitnum] "i" (1 << (bit & 7)), + [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3]) + : : t_yes, t_no); +t_yes: + return true; +t_no: + return false; +} + +#define static_cpu_has(bit) \ +( \ + __builtin_constant_p(boot_cpu_has(bit)) ? \ + boot_cpu_has(bit) : \ + _static_cpu_has(bit) \ +) +#endif + +#define cpu_has_bug(c, bit) cpu_has(c, (bit)) +#define set_cpu_bug(c, bit) set_cpu_cap(c, (bit)) +#define clear_cpu_bug(c, bit) clear_cpu_cap(c, (bit)) + +#define static_cpu_has_bug(bit) static_cpu_has((bit)) +#define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit)) +#define boot_cpu_set_bug(bit) set_cpu_cap(&boot_cpu_data, (bit)) + +#define MAX_CPU_FEATURES (NCAPINTS * 32) +#define cpu_have_feature boot_cpu_has + +#define CPU_FEATURE_TYPEFMT "x86,ven%04Xfam%04Xmod%04X" +#define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \ + boot_cpu_data.x86_model + +#endif /* defined(__KERNEL__) */ +#endif /* !defined(__ASSEMBLY__) */ +#endif /* _ASM_X86_CPUFEATURE_H */ diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h index cc96e26d69f7..dddc746b5455 100644 --- a/tools/arch/x86/include/asm/cpufeatures.h +++ b/tools/arch/x86/include/asm/cpufeatures.h @@ -290,6 +290,8 @@ #define X86_FEATURE_FENCE_SWAPGS_KERNEL (11*32+ 5) /* "" LFENCE in kernel entry SWAPGS path */ #define X86_FEATURE_SPLIT_LOCK_DETECT (11*32+ 6) /* #AC for split lock */ #define X86_FEATURE_PER_THREAD_MBA (11*32+ 7) /* "" Per-thread Memory Bandwidth Allocation */ +#define X86_FEATURE_SGX1 (11*32+ 8) /* "" Basic SGX */ +#define X86_FEATURE_SGX2 (11*32+ 9) /* "" SGX Enclave Dynamic Memory Management (EDMM) */ /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ #define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */ @@ -336,6 +338,7 @@ #define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */ #define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* Virtual VMSAVE VMLOAD */ #define X86_FEATURE_VGIF (15*32+16) /* Virtual GIF */ +#define X86_FEATURE_V_SPEC_CTRL (15*32+20) /* Virtual SPEC_CTRL */ #define X86_FEATURE_SVME_ADDR_CHK (15*32+28) /* "" SVME addr check */ /* Intel-defined CPU features, CPUID level 0x00000007:0 (ECX), word 16 */ diff --git a/tools/testing/selftests/kvm/include/x86_64/reverse_cpuid.h b/tools/testing/selftests/kvm/include/x86_64/reverse_cpuid.h new file mode 100644 index 000000000000..8e0756ddab1a --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86_64/reverse_cpuid.h @@ -0,0 +1,185 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef ARCH_X86_KVM_REVERSE_CPUID_H +#define ARCH_X86_KVM_REVERSE_CPUID_H + +#include +#include +#include + +/* + * Hardware-defined CPUID leafs that are scattered in the kernel, but need to + * be directly used by KVM. Note, these word values conflict with the kernel's + * "bug" caps, but KVM doesn't use those. + */ +enum kvm_only_cpuid_leafs { + CPUID_12_EAX = NCAPINTS, + NR_KVM_CPU_CAPS, + + NKVMCAPINTS = NR_KVM_CPU_CAPS - NCAPINTS, +}; + +#define KVM_X86_FEATURE(w, f) ((w)*32 + (f)) + +/* Intel-defined SGX sub-features, CPUID level 0x12 (EAX). */ +#define KVM_X86_FEATURE_SGX1 KVM_X86_FEATURE(CPUID_12_EAX, 0) +#define KVM_X86_FEATURE_SGX2 KVM_X86_FEATURE(CPUID_12_EAX, 1) + +struct cpuid_reg { + u32 function; + u32 index; + int reg; +}; + +static const struct cpuid_reg reverse_cpuid[] = { + [CPUID_1_EDX] = { 1, 0, CPUID_EDX}, + [CPUID_8000_0001_EDX] = {0x80000001, 0, CPUID_EDX}, + [CPUID_8086_0001_EDX] = {0x80860001, 0, CPUID_EDX}, + [CPUID_1_ECX] = { 1, 0, CPUID_ECX}, + [CPUID_C000_0001_EDX] = {0xc0000001, 0, CPUID_EDX}, + [CPUID_8000_0001_ECX] = {0x80000001, 0, CPUID_ECX}, + [CPUID_7_0_EBX] = { 7, 0, CPUID_EBX}, + [CPUID_D_1_EAX] = { 0xd, 1, CPUID_EAX}, + [CPUID_8000_0008_EBX] = {0x80000008, 0, CPUID_EBX}, + [CPUID_6_EAX] = { 6, 0, CPUID_EAX}, + [CPUID_8000_000A_EDX] = {0x8000000a, 0, CPUID_EDX}, + [CPUID_7_ECX] = { 7, 0, CPUID_ECX}, + [CPUID_8000_0007_EBX] = {0x80000007, 0, CPUID_EBX}, + [CPUID_7_EDX] = { 7, 0, CPUID_EDX}, + [CPUID_7_1_EAX] = { 7, 1, CPUID_EAX}, + [CPUID_12_EAX] = {0x00000012, 0, CPUID_EAX}, +}; + +/* + * Reverse CPUID and its derivatives can only be used for hardware-defined + * feature words, i.e. words whose bits directly correspond to a CPUID leaf. + * Retrieving a feature bit or masking guest CPUID from a Linux-defined word + * is nonsensical as the bit number/mask is an arbitrary software-defined value + * and can't be used by KVM to query/control guest capabilities. And obviously + * the leaf being queried must have an entry in the lookup table. + */ +static __always_inline void reverse_cpuid_check(unsigned int x86_leaf) +{ + BUILD_BUG_ON(x86_leaf == CPUID_LNX_1); + BUILD_BUG_ON(x86_leaf == CPUID_LNX_2); + BUILD_BUG_ON(x86_leaf == CPUID_LNX_3); + BUILD_BUG_ON(x86_leaf == CPUID_LNX_4); + BUILD_BUG_ON(x86_leaf >= ARRAY_SIZE(reverse_cpuid)); + BUILD_BUG_ON(reverse_cpuid[x86_leaf].function == 0); +} + +/* + * Translate feature bits that are scattered in the kernel's cpufeatures word + * into KVM feature words that align with hardware's definitions. + */ +static __always_inline u32 __feature_translate(int x86_feature) +{ + if (x86_feature == X86_FEATURE_SGX1) + return KVM_X86_FEATURE_SGX1; + else if (x86_feature == X86_FEATURE_SGX2) + return KVM_X86_FEATURE_SGX2; + + return x86_feature; +} + +static __always_inline u32 __feature_leaf(int x86_feature) +{ + return __feature_translate(x86_feature) / 32; +} + +/* + * Retrieve the bit mask from an X86_FEATURE_* definition. Features contain + * the hardware defined bit number (stored in bits 4:0) and a software defined + * "word" (stored in bits 31:5). The word is used to index into arrays of + * bit masks that hold the per-cpu feature capabilities, e.g. this_cpu_has(). + */ +static __always_inline u32 __feature_bit(int x86_feature) +{ + x86_feature = __feature_translate(x86_feature); + + reverse_cpuid_check(x86_feature / 32); + return 1 << (x86_feature & 31); +} + +#define feature_bit(name) __feature_bit(X86_FEATURE_##name) + +static __always_inline struct cpuid_reg x86_feature_cpuid(unsigned int x86_feature) +{ + unsigned int x86_leaf = __feature_leaf(x86_feature); + + reverse_cpuid_check(x86_leaf); + return reverse_cpuid[x86_leaf]; +} + +static __always_inline u32 *__cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, + u32 reg) +{ + switch (reg) { + case CPUID_EAX: + return &entry->eax; + case CPUID_EBX: + return &entry->ebx; + case CPUID_ECX: + return &entry->ecx; + case CPUID_EDX: + return &entry->edx; + default: + BUILD_BUG(); + return NULL; + } +} + +static __always_inline u32 *cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, + unsigned int x86_feature) +{ + const struct cpuid_reg cpuid = x86_feature_cpuid(x86_feature); + + return __cpuid_entry_get_reg(entry, cpuid.reg); +} + +static __always_inline u32 cpuid_entry_get(struct kvm_cpuid_entry2 *entry, + unsigned int x86_feature) +{ + u32 *reg = cpuid_entry_get_reg(entry, x86_feature); + + return *reg & __feature_bit(x86_feature); +} + +static __always_inline bool cpuid_entry_has(struct kvm_cpuid_entry2 *entry, + unsigned int x86_feature) +{ + return cpuid_entry_get(entry, x86_feature); +} + +static __always_inline void cpuid_entry_clear(struct kvm_cpuid_entry2 *entry, + unsigned int x86_feature) +{ + u32 *reg = cpuid_entry_get_reg(entry, x86_feature); + + *reg &= ~__feature_bit(x86_feature); +} + +static __always_inline void cpuid_entry_set(struct kvm_cpuid_entry2 *entry, + unsigned int x86_feature) +{ + u32 *reg = cpuid_entry_get_reg(entry, x86_feature); + + *reg |= __feature_bit(x86_feature); +} + +static __always_inline void cpuid_entry_change(struct kvm_cpuid_entry2 *entry, + unsigned int x86_feature, + bool set) +{ + u32 *reg = cpuid_entry_get_reg(entry, x86_feature); + + /* + * Open coded instead of using cpuid_entry_{clear,set}() to coerce the + * compiler into using CMOV instead of Jcc when possible. + */ + if (set) + *reg |= __feature_bit(x86_feature); + else + *reg &= ~__feature_bit(x86_feature); +} + +#endif /* ARCH_X86_KVM_REVERSE_CPUID_H */ From patchwork Thu Apr 22 00:56:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Koller X-Patchwork-Id: 12217261 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9A350C433B4 for ; Thu, 22 Apr 2021 00:57:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6DE9861424 for ; Thu, 22 Apr 2021 00:57:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244406AbhDVA5h (ORCPT ); Wed, 21 Apr 2021 20:57:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54990 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244342AbhDVA5e (ORCPT ); Wed, 21 Apr 2021 20:57:34 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EFAAEC06138B for ; Wed, 21 Apr 2021 17:56:58 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id e65-20020a25e7440000b02904ecfeff1ed8so6586369ybh.19 for ; Wed, 21 Apr 2021 17:56:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=d4FQCYHivptxQk4kA1SJ6N+YreUjXRXnuN7O1SBVzug=; b=Wsya/lSsSo7Yxan02JvA7mnccp0K4Zos4f7NT3FGyZtavc9Lz7YzkTnd6tcQO5Xq7I hVhG5nXfQYXITIito2k8elrNnGPq1GbeXs3l5X9YyKSkcVyxbtYvOOiNp+y4PmSBDWQh 9b30cM8ZSuLnN+5roW/z9Gkf6xeYmhPAAVVohmUEIboUgHPAi4kyhTlkItHaX4lfoZRA q8lEOVaQiy+EUWwVNU9y/lPXKGRh8a/NJlacyw6E5pNQZ1I95tH9dHE/ao+toVsNKrYp Aam2Qx38ZXdapQcVUTSxNvTLVRvVixxejj1fx0bOS7YjhiAloSdeclW9JtFGU6ogN04t c6XQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=d4FQCYHivptxQk4kA1SJ6N+YreUjXRXnuN7O1SBVzug=; b=mx6ATUsGyAestKqysMSbBc/jNTAJrzAYZSh/cFunqGXemDxKZ18J7uV4VidneHeEA9 yXuOS2Uou0W2fyiedL4AZU0PZWrLoIOlJJ833bewuurMp/lT81KozI3WVGmgD2Rsq8uK +4iB9EiiFJJ9/efcZmoZwQK6sPM7jp2u63VKWjhbaehIkidmiUMmPCRAnx4wwCiMv1dL KwBxhmTltG3lWa6FSYS8wwi0bz8RDVqlgMe9QuLuJaCg6ld7+FetSPsjtAfsnJsGRVo0 CKvDKuugNClH37Q2behtc+Jl/Fp5+cSgb/IZtVJCd+R/5BjyKXTBaiwSJTOI5z9XPplS 3dIg== X-Gm-Message-State: AOAM531b3dyAG1746OzturlHHjfHm5Rs8wTfhgoYABN4OZ3lSKJMWCOd n7z1B6xip+dQftgICxcRDbGOI2xpwqS99A== X-Google-Smtp-Source: ABdhPJzFrB6SBU8DgXRInxWJXederj8nDe1SUbPCu0j0My+G/hbNToOQzZmf2TTEtEoISvg6Trv+VVUXbtwh1w== X-Received: from ricarkol2.c.googlers.com ([fda3:e722:ac3:10:24:72f4:c0a8:62fe]) (user=ricarkol job=sendgmr) by 2002:a25:42cd:: with SMTP id p196mr1082067yba.314.1619053018241; Wed, 21 Apr 2021 17:56:58 -0700 (PDT) Date: Wed, 21 Apr 2021 17:56:25 -0700 In-Reply-To: <20210422005626.564163-1-ricarkol@google.com> Message-Id: <20210422005626.564163-5-ricarkol@google.com> Mime-Version: 1.0 References: <20210422005626.564163-1-ricarkol@google.com> X-Mailer: git-send-email 2.31.1.368.gbe11c130af-goog Subject: [PATCH 4/5] KVM: selftests: Introduce utilities for checking x86 features From: Ricardo Koller To: Paolo Bonzini Cc: kvm@vger.kernel.org, Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , "H. Peter Anvin" , Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , Nathan Chancellor , Nick Desaulniers , linux-kernel@vger.kernel.org, clang-built-linux@googlegroups.com, Ricardo Koller Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add utilities for checking CPU features using the same x86 features format used in the kernel (defined in cpufeatures.h). This format embeds the function, index, and register to use. By using this format and these utilities, tests will not have to define their own feature macros and will be able to use kvm_cpuid_has(FEATURE_XYZ) or this_cpu_has(FEATURE_XYZ) without having to worry about what register or index to use. Signed-off-by: Ricardo Koller --- .../selftests/kvm/include/x86_64/cpuid.h | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 tools/testing/selftests/kvm/include/x86_64/cpuid.h diff --git a/tools/testing/selftests/kvm/include/x86_64/cpuid.h b/tools/testing/selftests/kvm/include/x86_64/cpuid.h new file mode 100644 index 000000000000..4d8c67d528f4 --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86_64/cpuid.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Adapted from /arch/x86/kvm/cpuid.h + */ + +#ifndef SELFTEST_KVM_CPUID_FEATURE_H +#define SELFTEST_KVM_CPUID_FEATURE_H + +#include +#include +#include +#include "reverse_cpuid.h" + +static __always_inline u32 *kvm_cpuid_get_register(unsigned int x86_feature) +{ + struct kvm_cpuid_entry2 *entry; + const struct cpuid_reg cpuid = x86_feature_cpuid(x86_feature); + + entry = kvm_get_supported_cpuid_index(cpuid.function, cpuid.index); + if (!entry) + return NULL; + + return __cpuid_entry_get_reg(entry, cpuid.reg); +} + +static __always_inline bool kvm_cpuid_has(unsigned int x86_feature) +{ + u32 *reg; + + reg = kvm_cpuid_get_register(x86_feature); + if (!reg) + return false; + + return *reg & __feature_bit(x86_feature); +} + +static __always_inline bool kvm_pv_has(unsigned int kvm_feature) +{ + u32 reg; + + reg = kvm_get_supported_cpuid_entry(KVM_CPUID_FEATURES)->eax; + return reg & __feature_bit(kvm_feature); +} + +static __always_inline bool this_cpu_has(unsigned int x86_feature) +{ + struct kvm_cpuid_entry2 entry; + const struct cpuid_reg cpuid = x86_feature_cpuid(x86_feature); + u32 *reg; + + entry.eax = cpuid.function; + entry.ecx = cpuid.index; + __asm__ __volatile__("cpuid" + : "+a"(entry.eax), "=b"(entry.ebx), + "+c"(entry.ecx), "=d"(entry.edx)); + + reg = __cpuid_entry_get_reg(&entry, cpuid.reg); + return *reg & __feature_bit(x86_feature); +} + +#endif /* SELFTEST_KVM_CPUID_FEATURE_H */ From patchwork Thu Apr 22 00:56:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Koller X-Patchwork-Id: 12217263 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C086C43461 for ; Thu, 22 Apr 2021 00:57:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F2D146142B for ; Thu, 22 Apr 2021 00:57:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343949AbhDVA5i (ORCPT ); Wed, 21 Apr 2021 20:57:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55000 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244351AbhDVA5e (ORCPT ); Wed, 21 Apr 2021 20:57:34 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6E3FAC06138D for ; Wed, 21 Apr 2021 17:57:00 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id o12-20020a17090ac70cb029014e1b69ef6dso40327pjt.0 for ; Wed, 21 Apr 2021 17:57:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Mp2tqK23tc8zMbZfL/Pl7tKa+i2zyXk9APFPF/poLXo=; b=c+Gg7CRAm6krPzXd16k1mZ+9rWMJBMTtfUxd6RAIgeFZL0cyAU1OF1zKKIS+UyfwiA I1KgpDzwnJmfxJzVo44K5bjTcY/B/bxjtx25mzjsF9Rc5EniiTCE5cVmh0a8spqccgWI Z5s1mzSZJ8ApZPwG0BfcJXpLcU+imQTipvSuUZeLeZPJZnqNRaUpzf/Cel9CRkweXhZ7 mgwuic84MMAHmMKPKjs4n6DKpxq93aRklBgdZcZxnMosiwHectBgOg3pNV0q95BHoCa3 seLn6kKaPIknLXcVBDhdgjg/mEfuQf9X2rRHLNDt0QNivHE3KD3R0z98ssrCRrcwmIot nNrQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Mp2tqK23tc8zMbZfL/Pl7tKa+i2zyXk9APFPF/poLXo=; b=j2IRelU+tRpb3lkH3boybdPWLLBLrQ7zbsg/JSDTaNu/CYfcKFmCLQgFKTWFT51VjG vHOYeX3KlsQkljAZ7RdQuLvN2nHOdhGLropjoo2xqqRw0z4eZPeTn2irDN6IrHutN8TX SgezF55QHZu/vuCMbwqmbmznSVDOs8vwQKkfW73NrtbFvclEun+bp0LYSPzucs1EqeNl gF8s3inVhb+6heK9GWwV2g969Fc61HebfjM+6OmuFGZ6FucBPj0kucBQCDVLvzyR87Iu cpb+zJGr7elZPvy1IxxF9ZPVwKDXKRDs7McZD7qyJR/RIB5U4fS+XRAcNMT2rp1WUp5l c3IQ== X-Gm-Message-State: AOAM5305ms2oL/Et4SJSgUs7GZnLX+5YtaubJB9kxoZrusYG9mmM9GK/ j/s8b4+p/XZRenFwLE5Fyp3lqPOXHUSxJQ== X-Google-Smtp-Source: ABdhPJyQ1GPqL173PMaF6Z+ADod0FJl1Q1vwwz/WPAFExvOS/EPcFZQ7VCAPAWdsSXKmQMlBNZw/aZjA4yq5ew== X-Received: from ricarkol2.c.googlers.com ([fda3:e722:ac3:10:24:72f4:c0a8:62fe]) (user=ricarkol job=sendgmr) by 2002:a17:902:361:b029:e9:8392:7abd with SMTP id 88-20020a1709020361b02900e983927abdmr809384pld.8.1619053019855; Wed, 21 Apr 2021 17:56:59 -0700 (PDT) Date: Wed, 21 Apr 2021 17:56:26 -0700 In-Reply-To: <20210422005626.564163-1-ricarkol@google.com> Message-Id: <20210422005626.564163-6-ricarkol@google.com> Mime-Version: 1.0 References: <20210422005626.564163-1-ricarkol@google.com> X-Mailer: git-send-email 2.31.1.368.gbe11c130af-goog Subject: [PATCH 5/5] KVM: selftests: Use kernel x86 cpuid features format From: Ricardo Koller To: Paolo Bonzini Cc: kvm@vger.kernel.org, Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , "H. Peter Anvin" , Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , Nathan Chancellor , Nick Desaulniers , linux-kernel@vger.kernel.org, clang-built-linux@googlegroups.com, Ricardo Koller Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Change all tests checking for x86 cpuid features to use the same cpuid feature definitions as the kernel (from cpufeatures.h). Also change the tests to use the utilities introduced in cpuid.h. Signed-off-by: Ricardo Koller --- .../selftests/kvm/include/x86_64/processor.h | 16 ------------ .../selftests/kvm/include/x86_64/svm_util.h | 11 ++------ tools/testing/selftests/kvm/lib/x86_64/svm.c | 6 ++--- tools/testing/selftests/kvm/lib/x86_64/vmx.c | 5 ++-- tools/testing/selftests/kvm/steal_time.c | 5 ++-- .../kvm/x86_64/cr4_cpuid_sync_test.c | 23 +++++------------ .../selftests/kvm/x86_64/set_sregs_test.c | 25 ++++++++----------- .../selftests/kvm/x86_64/vmx_pmu_msrs_test.c | 8 +++--- .../kvm/x86_64/vmx_set_nested_state_test.c | 5 ++-- .../selftests/kvm/x86_64/xss_msr_test.c | 10 +++----- 10 files changed, 36 insertions(+), 78 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h index 0b30b4e15c38..022e00b04fff 100644 --- a/tools/testing/selftests/kvm/include/x86_64/processor.h +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h @@ -37,22 +37,6 @@ #define X86_CR4_SMAP (1ul << 21) #define X86_CR4_PKE (1ul << 22) -/* CPUID.1.ECX */ -#define CPUID_VMX (1ul << 5) -#define CPUID_SMX (1ul << 6) -#define CPUID_PCID (1ul << 17) -#define CPUID_XSAVE (1ul << 26) - -/* CPUID.7.EBX */ -#define CPUID_FSGSBASE (1ul << 0) -#define CPUID_SMEP (1ul << 7) -#define CPUID_SMAP (1ul << 20) - -/* CPUID.7.ECX */ -#define CPUID_UMIP (1ul << 2) -#define CPUID_PKU (1ul << 3) -#define CPUID_LA57 (1ul << 16) - #define UNEXPECTED_VECTOR_PORT 0xfff0u /* General Registers in 64-Bit Mode */ diff --git a/tools/testing/selftests/kvm/include/x86_64/svm_util.h b/tools/testing/selftests/kvm/include/x86_64/svm_util.h index b7531c83b8ae..adba82ff4c9b 100644 --- a/tools/testing/selftests/kvm/include/x86_64/svm_util.h +++ b/tools/testing/selftests/kvm/include/x86_64/svm_util.h @@ -12,9 +12,7 @@ #include #include "svm.h" #include "processor.h" - -#define CPUID_SVM_BIT 2 -#define CPUID_SVM BIT_ULL(CPUID_SVM_BIT) +#include "cpuid.h" #define SVM_EXIT_VMMCALL 0x081 @@ -38,12 +36,7 @@ void nested_svm_check_supported(void); static inline bool cpu_has_svm(void) { - u32 eax = 0x80000001, ecx; - - asm("cpuid" : - "=a" (eax), "=c" (ecx) : "0" (eax) : "ebx", "edx"); - - return ecx & CPUID_SVM; + return this_cpu_has(X86_FEATURE_SVM); } #endif /* SELFTEST_KVM_SVM_UTILS_H */ diff --git a/tools/testing/selftests/kvm/lib/x86_64/svm.c b/tools/testing/selftests/kvm/lib/x86_64/svm.c index 827fe6028dd4..c68245233cf9 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/svm.c +++ b/tools/testing/selftests/kvm/lib/x86_64/svm.c @@ -12,6 +12,7 @@ #include "../kvm_util_internal.h" #include "processor.h" #include "svm_util.h" +#include "cpuid.h" struct gpr64_regs guest_regs; u64 rflags; @@ -150,10 +151,7 @@ void run_guest(struct vmcb *vmcb, uint64_t vmcb_gpa) bool nested_svm_supported(void) { - struct kvm_cpuid_entry2 *entry = - kvm_get_supported_cpuid_entry(0x80000001); - - return entry->ecx & CPUID_SVM; + return kvm_cpuid_has(X86_FEATURE_SVM); } void nested_svm_check_supported(void) diff --git a/tools/testing/selftests/kvm/lib/x86_64/vmx.c b/tools/testing/selftests/kvm/lib/x86_64/vmx.c index 2448b30e8efa..be26dcd260a4 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/vmx.c +++ b/tools/testing/selftests/kvm/lib/x86_64/vmx.c @@ -10,6 +10,7 @@ #include "../kvm_util_internal.h" #include "processor.h" #include "vmx.h" +#include "cpuid.h" #define PAGE_SHIFT_4K 12 @@ -381,9 +382,7 @@ void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp) bool nested_vmx_supported(void) { - struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1); - - return entry->ecx & CPUID_VMX; + return kvm_cpuid_has(X86_FEATURE_VMX); } void nested_vmx_check_supported(void) diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c index fcc840088c91..04d86601de92 100644 --- a/tools/testing/selftests/kvm/steal_time.c +++ b/tools/testing/selftests/kvm/steal_time.c @@ -27,6 +27,8 @@ static uint64_t guest_stolen_time[NR_VCPUS]; #if defined(__x86_64__) +#include "cpuid.h" + /* steal_time must have 64-byte alignment */ #define STEAL_TIME_SIZE ((sizeof(struct kvm_steal_time) + 63) & ~63) @@ -64,8 +66,7 @@ static void steal_time_init(struct kvm_vm *vm) { int i; - if (!(kvm_get_supported_cpuid_entry(KVM_CPUID_FEATURES)->eax & - KVM_FEATURE_STEAL_TIME)) { + if (!kvm_pv_has(KVM_FEATURE_STEAL_TIME)) { print_skip("steal-time not supported"); exit(KSFT_SKIP); } diff --git a/tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c b/tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c index f40fd097cb35..97e97b258983 100644 --- a/tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c +++ b/tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c @@ -18,26 +18,17 @@ #include "kvm_util.h" #include "processor.h" +#include "cpuid.h" -#define X86_FEATURE_XSAVE (1<<26) -#define X86_FEATURE_OSXSAVE (1<<27) #define VCPU_ID 1 static inline bool cr4_cpuid_is_sync(void) { - int func, subfunc; - uint32_t eax, ebx, ecx, edx; - uint64_t cr4; - - func = 0x1; - subfunc = 0x0; - __asm__ __volatile__("cpuid" - : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) - : "a"(func), "c"(subfunc)); - - cr4 = get_cr4(); + uint64_t cr4 = get_cr4(); + bool cpuid_has_osxsave = this_cpu_has(X86_FEATURE_OSXSAVE); + bool cr4_has_osxsave = cr4 & X86_CR4_OSXSAVE; - return (!!(ecx & X86_FEATURE_OSXSAVE)) == (!!(cr4 & X86_CR4_OSXSAVE)); + return cpuid_has_osxsave == cr4_has_osxsave; } static void guest_code(void) @@ -66,12 +57,10 @@ int main(int argc, char *argv[]) struct kvm_run *run; struct kvm_vm *vm; struct kvm_sregs sregs; - struct kvm_cpuid_entry2 *entry; struct ucall uc; int rc; - entry = kvm_get_supported_cpuid_entry(1); - if (!(entry->ecx & X86_FEATURE_XSAVE)) { + if (!kvm_cpuid_has(X86_FEATURE_XSAVE)) { print_skip("XSAVE feature not supported"); return 0; } diff --git a/tools/testing/selftests/kvm/x86_64/set_sregs_test.c b/tools/testing/selftests/kvm/x86_64/set_sregs_test.c index 318be0bf77ab..e3247f33d765 100644 --- a/tools/testing/selftests/kvm/x86_64/set_sregs_test.c +++ b/tools/testing/selftests/kvm/x86_64/set_sregs_test.c @@ -21,6 +21,7 @@ #include "kvm_util.h" #include "processor.h" +#include "cpuid.h" #define VCPU_ID 5 @@ -47,34 +48,30 @@ static void test_cr4_feature_bit(struct kvm_vm *vm, struct kvm_sregs *orig, static uint64_t calc_cr4_feature_bits(struct kvm_vm *vm) { - struct kvm_cpuid_entry2 *cpuid_1, *cpuid_7; uint64_t cr4; - cpuid_1 = kvm_get_supported_cpuid_entry(1); - cpuid_7 = kvm_get_supported_cpuid_entry(7); - cr4 = X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT; - if (cpuid_7->ecx & CPUID_UMIP) + if (kvm_cpuid_has(X86_FEATURE_UMIP)) cr4 |= X86_CR4_UMIP; - if (cpuid_7->ecx & CPUID_LA57) + if (kvm_cpuid_has(X86_FEATURE_LA57)) cr4 |= X86_CR4_LA57; - if (cpuid_1->ecx & CPUID_VMX) + if (kvm_cpuid_has(X86_FEATURE_VMX)) cr4 |= X86_CR4_VMXE; - if (cpuid_1->ecx & CPUID_SMX) + if (kvm_cpuid_has(X86_FEATURE_SMX)) cr4 |= X86_CR4_SMXE; - if (cpuid_7->ebx & CPUID_FSGSBASE) + if (kvm_cpuid_has(X86_FEATURE_FSGSBASE)) cr4 |= X86_CR4_FSGSBASE; - if (cpuid_1->ecx & CPUID_PCID) + if (kvm_cpuid_has(X86_FEATURE_PCID)) cr4 |= X86_CR4_PCIDE; - if (cpuid_1->ecx & CPUID_XSAVE) + if (kvm_cpuid_has(X86_FEATURE_XSAVE)) cr4 |= X86_CR4_OSXSAVE; - if (cpuid_7->ebx & CPUID_SMEP) + if (kvm_cpuid_has(X86_FEATURE_SMEP)) cr4 |= X86_CR4_SMEP; - if (cpuid_7->ebx & CPUID_SMAP) + if (kvm_cpuid_has(X86_FEATURE_SMAP)) cr4 |= X86_CR4_SMAP; - if (cpuid_7->ecx & CPUID_PKU) + if (kvm_cpuid_has(X86_FEATURE_PKU)) cr4 |= X86_CR4_PKE; return cr4; diff --git a/tools/testing/selftests/kvm/x86_64/vmx_pmu_msrs_test.c b/tools/testing/selftests/kvm/x86_64/vmx_pmu_msrs_test.c index 23051d84b907..3755451f4877 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_pmu_msrs_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_pmu_msrs_test.c @@ -17,10 +17,10 @@ #include "kvm_util.h" #include "vmx.h" +#include "cpuid.h" #define VCPU_ID 0 -#define X86_FEATURE_PDCM (1<<15) #define PMU_CAP_FW_WRITES (1ULL << 13) #define PMU_CAP_LBR_FMT 0x3f @@ -76,7 +76,7 @@ int main(int argc, char *argv[]) if (kvm_get_cpuid_max_basic() >= 0xa) { entry_1_0 = kvm_get_supported_cpuid_index(1, 0); entry_a_0 = kvm_get_supported_cpuid_index(0xa, 0); - pdcm_supported = entry_1_0 && !!(entry_1_0->ecx & X86_FEATURE_PDCM); + pdcm_supported = kvm_cpuid_has(X86_FEATURE_PDCM); eax.full = entry_a_0->eax; } if (!pdcm_supported) { @@ -111,13 +111,13 @@ int main(int argc, char *argv[]) TEST_ASSERT(ret == 0, "Bad PERF_CAPABILITIES didn't fail."); /* testcase 4, set capabilities when we don't have PDCM bit */ - entry_1_0->ecx &= ~X86_FEATURE_PDCM; + entry_1_0->ecx &= ~feature_bit(PDCM); vcpu_set_cpuid(vm, VCPU_ID, cpuid); ret = _vcpu_set_msr(vm, 0, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities); TEST_ASSERT(ret == 0, "Bad PERF_CAPABILITIES didn't fail."); /* testcase 5, set capabilities when we don't have PMU version bits */ - entry_1_0->ecx |= X86_FEATURE_PDCM; + entry_1_0->ecx |= feature_bit(PDCM); eax.split.version_id = 0; entry_1_0->ecx = eax.full; vcpu_set_cpuid(vm, VCPU_ID, cpuid); diff --git a/tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c b/tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c index 5827b9bae468..bea74c9ef0f7 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c @@ -11,6 +11,7 @@ #include "kvm_util.h" #include "processor.h" #include "vmx.h" +#include "cpuid.h" #include #include @@ -255,9 +256,9 @@ void disable_vmx(struct kvm_vm *vm) break; TEST_ASSERT(i != cpuid->nent, "CPUID function 1 not found"); - cpuid->entries[i].ecx &= ~CPUID_VMX; + cpuid->entries[i].ecx &= ~feature_bit(VMX); vcpu_set_cpuid(vm, VCPU_ID, cpuid); - cpuid->entries[i].ecx |= CPUID_VMX; + cpuid->entries[i].ecx |= feature_bit(VMX); } int main(int argc, char *argv[]) diff --git a/tools/testing/selftests/kvm/x86_64/xss_msr_test.c b/tools/testing/selftests/kvm/x86_64/xss_msr_test.c index 3529376747c2..962dbb63cffe 100644 --- a/tools/testing/selftests/kvm/x86_64/xss_msr_test.c +++ b/tools/testing/selftests/kvm/x86_64/xss_msr_test.c @@ -11,12 +11,11 @@ #include "test_util.h" #include "kvm_util.h" #include "vmx.h" +#include "cpuid.h" #define VCPU_ID 1 #define MSR_BITS 64 -#define X86_FEATURE_XSAVES (1<<3) - bool is_supported_msr(u32 msr_index) { struct kvm_msr_list *list; @@ -37,7 +36,6 @@ bool is_supported_msr(u32 msr_index) int main(int argc, char *argv[]) { - struct kvm_cpuid_entry2 *entry; bool xss_supported = false; struct kvm_vm *vm; uint64_t xss_val; @@ -46,10 +44,8 @@ int main(int argc, char *argv[]) /* Create VM */ vm = vm_create_default(VCPU_ID, 0, 0); - if (kvm_get_cpuid_max_basic() >= 0xd) { - entry = kvm_get_supported_cpuid_index(0xd, 1); - xss_supported = entry && !!(entry->eax & X86_FEATURE_XSAVES); - } + if (kvm_get_cpuid_max_basic() >= 0xd) + xss_supported = kvm_cpuid_has(X86_FEATURE_XSAVES); if (!xss_supported) { print_skip("IA32_XSS is not supported by the vCPU"); exit(KSFT_SKIP);