From: Kai Huang <kai.huang@intel.com>
To: linux-sgx@vger.kernel.org, kvm@vger.kernel.org, x86@kernel.org
Cc: seanjc@google.com, jarkko@kernel.org, luto@kernel.org,
dave.hansen@intel.com, rick.p.edgecombe@intel.com,
haitao.huang@intel.com, pbonzini@redhat.com, bp@alien8.de,
tglx@linutronix.de, mingo@redhat.com, hpa@zytor.com,
jmattson@google.com, joro@8bytes.org, vkuznets@redhat.com,
wanpengli@tencent.com, Kai Huang <kai.huang@intel.com>
Subject: [RFC PATCH v5 18/26] KVM: x86: Add support for reverse CPUID lookup of scattered features
Date: Sun, 14 Feb 2021 02:29:46 +1300 [thread overview]
Message-ID: <d1d414379f374825c2d5e04a805f990888568a7a.1613221549.git.kai.huang@intel.com> (raw)
In-Reply-To: <cover.1613221549.git.kai.huang@intel.com>
From: Sean Christopherson <seanjc@google.com>
Introduce a scheme that allows KVM's CPUID magic to support features
that are scattered in the kernel's feature words. To advertise and/or
query guest support for CPUID-based features, KVM requires the bit
number of an X86_FEATURE_* to match the bit number in its associated
CPUID entry. For scattered features, this does not hold true.
Add a framework to allow defining KVM-only words, stored in
kvm_cpu_caps after the shared kernel caps, that can be used to gather
the scattered feature bits by translating X86_FEATURE_* flags into their
KVM-defined feature.
Note, because reverse_cpuid_check() effectively forces kvm_cpu_caps
lookups to be resolved at compile time, there is no runtime cost for
translating from kernel-defined to kvm-defined features.
More details here: https://lkml.kernel.org/r/X/jxCOLG+HUO4QlZ@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Kai Huang <kai.huang@intel.com>
---
arch/x86/kvm/cpuid.c | 32 +++++++++++++++++++++++++++-----
arch/x86/kvm/cpuid.h | 39 ++++++++++++++++++++++++++++++++++-----
2 files changed, 61 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 13036cf0b912..f8037fab8950 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -28,7 +28,7 @@
* Unlike "struct cpuinfo_x86.x86_capability", kvm_cpu_caps doesn't need to be
* aligned to sizeof(unsigned long) because it's not accessed via bitops.
*/
-u32 kvm_cpu_caps[NCAPINTS] __read_mostly;
+u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly;
EXPORT_SYMBOL_GPL(kvm_cpu_caps);
static u32 xstate_required_size(u64 xstate_bv, bool compacted)
@@ -53,6 +53,7 @@ static u32 xstate_required_size(u64 xstate_bv, bool compacted)
}
#define F feature_bit
+#define SF(name) (boot_cpu_has(X86_FEATURE_##name) ? F(name) : 0)
static inline struct kvm_cpuid_entry2 *cpuid_entry2_find(
struct kvm_cpuid_entry2 *entries, int nent, u32 function, u32 index)
@@ -331,13 +332,13 @@ int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
return r;
}
-static __always_inline void kvm_cpu_cap_mask(enum cpuid_leafs leaf, u32 mask)
+/* Mask kvm_cpu_caps for @leaf with the raw CPUID capabilities of this CPU. */
+static __always_inline void __kvm_cpu_cap_mask(enum cpuid_leafs leaf)
{
const struct cpuid_reg cpuid = x86_feature_cpuid(leaf * 32);
struct kvm_cpuid_entry2 entry;
reverse_cpuid_check(leaf);
- kvm_cpu_caps[leaf] &= mask;
cpuid_count(cpuid.function, cpuid.index,
&entry.eax, &entry.ebx, &entry.ecx, &entry.edx);
@@ -345,6 +346,26 @@ static __always_inline void kvm_cpu_cap_mask(enum cpuid_leafs leaf, u32 mask)
kvm_cpu_caps[leaf] &= *__cpuid_entry_get_reg(&entry, cpuid.reg);
}
+static __always_inline void kvm_cpu_cap_mask(enum cpuid_leafs leaf, u32 mask)
+{
+ /* Use the "init" variant for scattered leafs. */
+ BUILD_BUG_ON(leaf >= NCAPINTS);
+
+ kvm_cpu_caps[leaf] &= mask;
+
+ __kvm_cpu_cap_mask(leaf);
+}
+
+static __always_inline void kvm_cpu_cap_init(enum cpuid_leafs leaf, u32 mask)
+{
+ /* Use the "mask" variant for hardwared-defined leafs. */
+ BUILD_BUG_ON(leaf < NCAPINTS);
+
+ kvm_cpu_caps[leaf] = mask;
+
+ __kvm_cpu_cap_mask(leaf);
+}
+
void kvm_set_cpu_caps(void)
{
unsigned int f_nx = is_efer_nx() ? F(NX) : 0;
@@ -355,12 +376,13 @@ void kvm_set_cpu_caps(void)
unsigned int f_gbpages = 0;
unsigned int f_lm = 0;
#endif
+ memset(kvm_cpu_caps, 0, sizeof(kvm_cpu_caps));
- BUILD_BUG_ON(sizeof(kvm_cpu_caps) >
+ BUILD_BUG_ON(sizeof(kvm_cpu_caps) - (NKVMCAPINTS * sizeof(*kvm_cpu_caps)) >
sizeof(boot_cpu_data.x86_capability));
memcpy(&kvm_cpu_caps, &boot_cpu_data.x86_capability,
- sizeof(kvm_cpu_caps));
+ sizeof(kvm_cpu_caps) - (NKVMCAPINTS * sizeof(*kvm_cpu_caps)));
kvm_cpu_cap_mask(CPUID_1_ECX,
/*
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index dc921d76e42e..2041e2f07347 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -7,7 +7,20 @@
#include <asm/processor.h>
#include <uapi/asm/kvm_para.h>
-extern u32 kvm_cpu_caps[NCAPINTS] __read_mostly;
+/*
+ * 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 {
+ NR_KVM_CPU_CAPS = NCAPINTS,
+
+ NKVMCAPINTS = NR_KVM_CPU_CAPS - NCAPINTS,
+};
+
+#define X86_KVM_FEATURE(w, f) ((w)*32 + (f))
+
+extern u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly;
void kvm_set_cpu_caps(void);
void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu);
@@ -83,6 +96,20 @@ static __always_inline void reverse_cpuid_check(unsigned int x86_leaf)
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)
+{
+ 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
@@ -91,6 +118,8 @@ static __always_inline void reverse_cpuid_check(unsigned int x86_leaf)
*/
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);
}
@@ -99,7 +128,7 @@ static __always_inline u32 __feature_bit(int x86_feature)
static __always_inline struct cpuid_reg x86_feature_cpuid(unsigned int x86_feature)
{
- unsigned int x86_leaf = x86_feature / 32;
+ unsigned int x86_leaf = __feature_leaf(x86_feature);
reverse_cpuid_check(x86_leaf);
return reverse_cpuid[x86_leaf];
@@ -291,7 +320,7 @@ static inline bool cpuid_fault_enabled(struct kvm_vcpu *vcpu)
static __always_inline void kvm_cpu_cap_clear(unsigned int x86_feature)
{
- unsigned int x86_leaf = x86_feature / 32;
+ unsigned int x86_leaf = __feature_leaf(x86_feature);
reverse_cpuid_check(x86_leaf);
kvm_cpu_caps[x86_leaf] &= ~__feature_bit(x86_feature);
@@ -299,7 +328,7 @@ static __always_inline void kvm_cpu_cap_clear(unsigned int x86_feature)
static __always_inline void kvm_cpu_cap_set(unsigned int x86_feature)
{
- unsigned int x86_leaf = x86_feature / 32;
+ unsigned int x86_leaf = __feature_leaf(x86_feature);
reverse_cpuid_check(x86_leaf);
kvm_cpu_caps[x86_leaf] |= __feature_bit(x86_feature);
@@ -307,7 +336,7 @@ static __always_inline void kvm_cpu_cap_set(unsigned int x86_feature)
static __always_inline u32 kvm_cpu_cap_get(unsigned int x86_feature)
{
- unsigned int x86_leaf = x86_feature / 32;
+ unsigned int x86_leaf = __feature_leaf(x86_feature);
reverse_cpuid_check(x86_leaf);
return kvm_cpu_caps[x86_leaf] & __feature_bit(x86_feature);
--
2.29.2
next prev parent reply other threads:[~2021-02-13 13:32 UTC|newest]
Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-13 13:28 [RFC PATCH v5 00/26] KVM SGX virtualization support Kai Huang
2021-02-13 13:28 ` [RFC PATCH v5 01/26] x86/cpufeatures: Make SGX_LC feature bit depend on SGX bit Kai Huang
2021-02-13 13:28 ` [RFC PATCH v5 02/26] x86/cpufeatures: Add SGX1 and SGX2 sub-features Kai Huang
2021-02-13 13:28 ` [RFC PATCH v5 03/26] x86/sgx: Wipe out EREMOVE from sgx_free_epc_page() Kai Huang
2021-02-16 17:04 ` Dave Hansen
2021-02-16 20:42 ` Huang, Kai
2021-02-13 13:28 ` [RFC PATCH v5 04/26] x86/sgx: Add SGX_CHILD_PRESENT hardware error code Kai Huang
2021-02-13 13:28 ` [RFC PATCH v5 05/26] x86/sgx: Introduce virtual EPC for use by KVM guests Kai Huang
2021-02-16 2:12 ` Jarkko Sakkinen
2021-02-16 18:38 ` Dave Hansen
2021-02-16 19:25 ` Sean Christopherson
2021-02-16 21:33 ` Huang, Kai
2021-02-16 21:34 ` Huang, Kai
2021-02-17 22:22 ` Jarkko Sakkinen
2021-02-13 13:29 ` [RFC PATCH v5 06/26] x86/cpu/intel: Allow SGX virtualization without Launch Control support Kai Huang
2021-02-16 2:15 ` Jarkko Sakkinen
2021-02-16 5:03 ` Huang, Kai
2021-02-16 8:36 ` Jarkko Sakkinen
2021-02-16 10:24 ` Huang, Kai
2021-02-16 18:40 ` Dave Hansen
2021-02-16 20:42 ` Huang, Kai
2021-02-13 13:29 ` [RFC PATCH v5 07/26] x86/sgx: Initialize virtual EPC driver even when SGX driver is disabled Kai Huang
2021-02-16 18:41 ` Dave Hansen
2021-02-13 13:29 ` [RFC PATCH v5 08/26] x86/sgx: Expose SGX architectural definitions to the kernel Kai Huang
2021-02-16 2:17 ` Jarkko Sakkinen
2021-02-16 10:30 ` Huang, Kai
2021-02-16 10:32 ` Borislav Petkov
2021-02-16 11:15 ` Huang, Kai
2021-02-16 11:48 ` Borislav Petkov
2021-02-16 11:56 ` Huang, Kai
2021-02-16 15:18 ` Dave Hansen
2021-02-16 18:47 ` Borislav Petkov
2021-02-16 18:53 ` Dave Hansen
2021-02-16 19:18 ` Borislav Petkov
2021-02-17 22:20 ` Jarkko Sakkinen
2021-02-18 9:09 ` Huang, Kai
2021-02-16 16:28 ` Jarkko Sakkinen
2021-02-13 13:29 ` [RFC PATCH v5 09/26] x86/sgx: Move ENCLS leaf definitions to sgx_arch.h Kai Huang
2021-02-13 13:29 ` [RFC PATCH v5 10/26] x86/sgx: Add SGX2 ENCLS leaf definitions (EAUG, EMODPR and EMODT) Kai Huang
2021-02-13 13:29 ` [RFC PATCH v5 11/26] x86/sgx: Add encls_faulted() helper Kai Huang
2021-02-13 13:29 ` [RFC PATCH v5 12/26] x86/sgx: Add helper to update SGX_LEPUBKEYHASHn MSRs Kai Huang
2021-02-13 13:29 ` [RFC PATCH v5 13/26] x86/sgx: Add helpers to expose ECREATE and EINIT to KVM Kai Huang
2021-02-16 3:08 ` Jarkko Sakkinen
2021-02-16 3:09 ` Jarkko Sakkinen
2021-02-16 4:55 ` Huang, Kai
2021-02-16 8:33 ` Jarkko Sakkinen
2021-02-16 8:35 ` Jarkko Sakkinen
2021-02-16 9:33 ` Huang, Kai
2021-02-13 13:29 ` [RFC PATCH v5 14/26] x86/sgx: Move provisioning device creation out of SGX driver Kai Huang
2021-02-13 13:29 ` [RFC PATCH v5 15/26] KVM: VMX: Convert vcpu_vmx.exit_reason to a union Kai Huang
2021-02-13 13:29 ` [RFC PATCH v5 16/26] KVM: x86: Export kvm_mmu_gva_to_gpa_{read,write}() for SGX (VMX) Kai Huang
2021-02-13 13:29 ` [RFC PATCH v5 17/26] KVM: x86: Define new #PF SGX error code bit Kai Huang
2021-02-13 13:29 ` Kai Huang [this message]
2021-02-13 13:29 ` [RFC PATCH v5 19/26] KVM: x86: Add reverse-CPUID lookup support for scattered SGX features Kai Huang
2021-02-13 13:29 ` [RFC PATCH v5 20/26] KVM: VMX: Add basic handling of VM-Exit from SGX enclave Kai Huang
2021-02-13 13:29 ` [RFC PATCH v5 21/26] KVM: VMX: Frame in ENCLS handler for SGX virtualization Kai Huang
2021-02-13 13:29 ` [RFC PATCH v5 22/26] KVM: VMX: Add SGX ENCLS[ECREATE] handler to enforce CPUID restrictions Kai Huang
2021-02-13 13:29 ` [RFC PATCH v5 23/26] KVM: VMX: Add emulation of SGX Launch Control LE hash MSRs Kai Huang
2021-02-13 13:29 ` [RFC PATCH v5 24/26] KVM: VMX: Add ENCLS[EINIT] handler to support SGX Launch Control (LC) Kai Huang
2021-02-13 13:29 ` [RFC PATCH v5 25/26] KVM: VMX: Enable SGX virtualization for SGX1, SGX2 and LC Kai Huang
2021-02-13 13:30 ` [RFC PATCH v5 26/26] KVM: x86: Add capability to grant VM access to privileged SGX attribute Kai Huang
2021-02-16 18:48 ` [RFC PATCH v5 00/26] KVM SGX virtualization support Dave Hansen
2021-02-16 19:15 ` Sean Christopherson
2021-02-16 20:58 ` Huang, Kai
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=d1d414379f374825c2d5e04a805f990888568a7a.1613221549.git.kai.huang@intel.com \
--to=kai.huang@intel.com \
--cc=bp@alien8.de \
--cc=dave.hansen@intel.com \
--cc=haitao.huang@intel.com \
--cc=hpa@zytor.com \
--cc=jarkko@kernel.org \
--cc=jmattson@google.com \
--cc=joro@8bytes.org \
--cc=kvm@vger.kernel.org \
--cc=linux-sgx@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mingo@redhat.com \
--cc=pbonzini@redhat.com \
--cc=rick.p.edgecombe@intel.com \
--cc=seanjc@google.com \
--cc=tglx@linutronix.de \
--cc=vkuznets@redhat.com \
--cc=wanpengli@tencent.com \
--cc=x86@kernel.org \
/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).