* [PATCH v2 1/4] target/i386: add support for FRED in CPUID enumeration
2023-10-02 7:23 [PATCH v2 0/4] target/i386: add support for FRED Xin Li
@ 2023-10-02 7:23 ` Xin Li
2023-10-02 7:23 ` [PATCH v2 2/4] target/i386: mark CR4.FRED not reserved Xin Li
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Xin Li @ 2023-10-02 7:23 UTC (permalink / raw)
To: qemu-devel
Cc: kvm, richard.henderson, pbonzini, eduardo, seanjc, chao.gao, hpa,
xiaoyao.li, weijiang.yang
FRED, i.e., the Intel flexible return and event delivery architecture,
defines simple new transitions that change privilege level (ring
transitions).
The new transitions defined by the FRED architecture are FRED event
delivery and, for returning from events, two FRED return instructions.
FRED event delivery can effect a transition from ring 3 to ring 0, but
it is used also to deliver events incident to ring 0. One FRED
instruction (ERETU) effects a return from ring 0 to ring 3, while the
other (ERETS) returns while remaining in ring 0. Collectively, FRED
event delivery and the FRED return instructions are FRED transitions.
In addition to these transitions, the FRED architecture defines a new
instruction (LKGS) for managing the state of the GS segment register.
The LKGS instruction can be used by 64-bit operating systems that do
not use the new FRED transitions.
Search for the latest FRED spec in most search engines with this search
pattern:
site:intel.com FRED (flexible return and event delivery) specification
The CPUID feature flag CPUID.(EAX=7,ECX=1):EAX[17] enumerates FRED, and
the CPUID feature flag CPUID.(EAX=7,ECX=1):EAX[18] enumerates LKGS.
Add CPUID definitions for FRED/LKGS, and expose them to KVM guests only.
Because FRED relies on LKGS, add it to feature dependency map.
Tested-by: Shan Kang <shan.kang@intel.com>
Signed-off-by: Xin Li <xin3.li@intel.com>
---
target/i386/cpu.c | 6 +++++-
target/i386/cpu.h | 4 ++++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index ed72883bf3..59fdb2a01a 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -963,7 +963,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
"avx-vnni", "avx512-bf16", NULL, "cmpccxadd",
NULL, NULL, "fzrm", "fsrs",
"fsrc", NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
+ NULL, "fred", "lkgs", NULL,
NULL, "amx-fp16", NULL, "avx-ifma",
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
@@ -1550,6 +1550,10 @@ static FeatureDep feature_dependencies[] = {
.from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE },
.to = { FEAT_7_0_ECX, CPUID_7_0_ECX_WAITPKG },
},
+ {
+ .from = { FEAT_7_1_EAX, CPUID_7_1_EAX_LKGS },
+ .to = { FEAT_7_1_EAX, CPUID_7_1_EAX_FRED },
+ },
};
typedef struct X86RegisterInfo32 {
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index d3f377d48a..e2946f1d6b 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -934,6 +934,10 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
#define CPUID_7_1_EDX_AMX_COMPLEX (1U << 8)
/* PREFETCHIT0/1 Instructions */
#define CPUID_7_1_EDX_PREFETCHITI (1U << 14)
+/* Flexible return and event delivery (FRED) */
+#define CPUID_7_1_EAX_FRED (1U << 17)
+/* Load into IA32_KERNEL_GS_BASE (LKGS) */
+#define CPUID_7_1_EAX_LKGS (1U << 18)
/* Do not exhibit MXCSR Configuration Dependent Timing (MCDT) behavior */
#define CPUID_7_2_EDX_MCDT_NO (1U << 5)
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/4] target/i386: mark CR4.FRED not reserved
2023-10-02 7:23 [PATCH v2 0/4] target/i386: add support for FRED Xin Li
2023-10-02 7:23 ` [PATCH v2 1/4] target/i386: add support for FRED in CPUID enumeration Xin Li
@ 2023-10-02 7:23 ` Xin Li
2023-10-02 7:23 ` [PATCH v2 3/4] target/i386: enumerate VMX nested-exception support Xin Li
2023-10-02 7:23 ` [PATCH v2 4/4] target/i386: Add get/set/migrate support for FRED MSRs Xin Li
3 siblings, 0 replies; 5+ messages in thread
From: Xin Li @ 2023-10-02 7:23 UTC (permalink / raw)
To: qemu-devel
Cc: kvm, richard.henderson, pbonzini, eduardo, seanjc, chao.gao, hpa,
xiaoyao.li, weijiang.yang
The CR4.FRED bit, i.e., CR4[32], is no longer a reserved bit when FRED
is exposed to guests, otherwise it is still a reserved bit.
Tested-by: Shan Kang <shan.kang@intel.com>
Signed-off-by: Xin Li <xin3.li@intel.com>
---
target/i386/cpu.h | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index e2946f1d6b..322547aa49 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -262,6 +262,12 @@ typedef enum X86Seg {
#define CR4_PKE_MASK (1U << 22)
#define CR4_PKS_MASK (1U << 24)
+#ifdef TARGET_X86_64
+#define CR4_FRED_MASK (1ULL << 32)
+#else
+#define CR4_FRED_MASK 0
+#endif
+
#define CR4_RESERVED_MASK \
(~(target_ulong)(CR4_VME_MASK | CR4_PVI_MASK | CR4_TSD_MASK \
| CR4_DE_MASK | CR4_PSE_MASK | CR4_PAE_MASK \
@@ -269,7 +275,8 @@ typedef enum X86Seg {
| CR4_OSFXSR_MASK | CR4_OSXMMEXCPT_MASK | CR4_UMIP_MASK \
| CR4_LA57_MASK \
| CR4_FSGSBASE_MASK | CR4_PCIDE_MASK | CR4_OSXSAVE_MASK \
- | CR4_SMEP_MASK | CR4_SMAP_MASK | CR4_PKE_MASK | CR4_PKS_MASK))
+ | CR4_SMEP_MASK | CR4_SMAP_MASK | CR4_PKE_MASK | CR4_PKS_MASK \
+ | CR4_FRED_MASK))
#define DR6_BD (1 << 13)
#define DR6_BS (1 << 14)
@@ -2484,6 +2491,9 @@ static inline uint64_t cr4_reserved_bits(CPUX86State *env)
if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKS)) {
reserved_bits |= CR4_PKS_MASK;
}
+ if (!(env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_FRED)) {
+ reserved_bits |= CR4_FRED_MASK;
+ }
return reserved_bits;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 3/4] target/i386: enumerate VMX nested-exception support
2023-10-02 7:23 [PATCH v2 0/4] target/i386: add support for FRED Xin Li
2023-10-02 7:23 ` [PATCH v2 1/4] target/i386: add support for FRED in CPUID enumeration Xin Li
2023-10-02 7:23 ` [PATCH v2 2/4] target/i386: mark CR4.FRED not reserved Xin Li
@ 2023-10-02 7:23 ` Xin Li
2023-10-02 7:23 ` [PATCH v2 4/4] target/i386: Add get/set/migrate support for FRED MSRs Xin Li
3 siblings, 0 replies; 5+ messages in thread
From: Xin Li @ 2023-10-02 7:23 UTC (permalink / raw)
To: qemu-devel
Cc: kvm, richard.henderson, pbonzini, eduardo, seanjc, chao.gao, hpa,
xiaoyao.li, weijiang.yang
Allow VMX nested-exception support to be exposed in KVM guests, thus
nested KVM guests can enumerate it.
Tested-by: Shan Kang <shan.kang@intel.com>
Signed-off-by: Xin Li <xin3.li@intel.com>
---
scripts/kvm/vmxcap | 1 +
target/i386/cpu.c | 1 +
target/i386/cpu.h | 1 +
3 files changed, 3 insertions(+)
diff --git a/scripts/kvm/vmxcap b/scripts/kvm/vmxcap
index 3fb4d5b342..97097518a8 100755
--- a/scripts/kvm/vmxcap
+++ b/scripts/kvm/vmxcap
@@ -116,6 +116,7 @@ controls = [
54: 'INS/OUTS instruction information',
55: 'IA32_VMX_TRUE_*_CTLS support',
56: 'Skip checks on event error code',
+ 58: 'VMX nested exception support',
},
msr = MSR_IA32_VMX_BASIC,
),
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 59fdb2a01a..da0876842f 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1341,6 +1341,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
[54] = "vmx-ins-outs",
[55] = "vmx-true-ctls",
[56] = "vmx-any-errcode",
+ [58] = "vmx-nested-exception",
},
.msr = {
.index = MSR_IA32_VMX_BASIC,
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 322547aa49..f4f0c57574 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1051,6 +1051,7 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
#define MSR_VMX_BASIC_INS_OUTS (1ULL << 54)
#define MSR_VMX_BASIC_TRUE_CTLS (1ULL << 55)
#define MSR_VMX_BASIC_ANY_ERRCODE (1ULL << 56)
+#define MSR_VMX_BASIC_NESTED_EXCEPTION (1ULL << 58)
#define MSR_VMX_MISC_PREEMPTION_TIMER_SHIFT_MASK 0x1Full
#define MSR_VMX_MISC_STORE_LMA (1ULL << 5)
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 4/4] target/i386: Add get/set/migrate support for FRED MSRs
2023-10-02 7:23 [PATCH v2 0/4] target/i386: add support for FRED Xin Li
` (2 preceding siblings ...)
2023-10-02 7:23 ` [PATCH v2 3/4] target/i386: enumerate VMX nested-exception support Xin Li
@ 2023-10-02 7:23 ` Xin Li
3 siblings, 0 replies; 5+ messages in thread
From: Xin Li @ 2023-10-02 7:23 UTC (permalink / raw)
To: qemu-devel
Cc: kvm, richard.henderson, pbonzini, eduardo, seanjc, chao.gao, hpa,
xiaoyao.li, weijiang.yang
FRED CPU states are managed in 9 new FRED MSRs, in addtion to a few
existing CPU registers and MSRs, e.g., CR4.FRED and MSR_IA32_PL0_SSP.
Save/restore/migrate FRED MSRs if FRED is exposed to the guest.
Tested-by: Shan Kang <shan.kang@intel.com>
Signed-off-by: Xin Li <xin3.li@intel.com>
---
target/i386/cpu.h | 26 +++++++++++++++++++++
target/i386/kvm/kvm.c | 54 +++++++++++++++++++++++++++++++++++++++++++
target/i386/machine.c | 29 +++++++++++++++++++++++
3 files changed, 109 insertions(+)
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index f4f0c57574..48e713ecc1 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -529,6 +529,20 @@ typedef enum X86Seg {
#define MSR_IA32_XFD 0x000001c4
#define MSR_IA32_XFD_ERR 0x000001c5
+#define MSR_IA32_PL0_SSP 0x000006a4 /* Stack level 0 shadow stack pointer in ring 0 */
+
+/* FRED MSRs */
+#define MSR_IA32_FRED_RSP0 0x000001cc /* Stack level 0 regular stack pointer */
+#define MSR_IA32_FRED_RSP1 0x000001cd /* Stack level 1 regular stack pointer */
+#define MSR_IA32_FRED_RSP2 0x000001ce /* Stack level 2 regular stack pointer */
+#define MSR_IA32_FRED_RSP3 0x000001cf /* Stack level 3 regular stack pointer */
+#define MSR_IA32_FRED_STKLVLS 0x000001d0 /* FRED exception stack levels */
+#define MSR_IA32_FRED_SSP0 MSR_IA32_PL0_SSP /* Stack level 0 shadow stack pointer in ring 0 */
+#define MSR_IA32_FRED_SSP1 0x000001d1 /* Stack level 1 shadow stack pointer in ring 0 */
+#define MSR_IA32_FRED_SSP2 0x000001d2 /* Stack level 2 shadow stack pointer in ring 0 */
+#define MSR_IA32_FRED_SSP3 0x000001d3 /* Stack level 3 shadow stack pointer in ring 0 */
+#define MSR_IA32_FRED_CONFIG 0x000001d4 /* FRED Entrypoint and interrupt stack level */
+
#define MSR_IA32_BNDCFGS 0x00000d90
#define MSR_IA32_XSS 0x00000da0
#define MSR_IA32_UMWAIT_CONTROL 0xe1
@@ -1684,6 +1698,18 @@ typedef struct CPUArchState {
target_ulong cstar;
target_ulong fmask;
target_ulong kernelgsbase;
+
+ /* FRED MSRs */
+ uint64_t fred_rsp0;
+ uint64_t fred_rsp1;
+ uint64_t fred_rsp2;
+ uint64_t fred_rsp3;
+ uint64_t fred_stklvls;
+ uint64_t fred_ssp0;
+ uint64_t fred_ssp1;
+ uint64_t fred_ssp2;
+ uint64_t fred_ssp3;
+ uint64_t fred_config;
#endif
uint64_t tsc_adjust;
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index f6c7f7e268..6ee3369a93 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -3399,6 +3399,18 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
kvm_msr_entry_add(cpu, MSR_KERNELGSBASE, env->kernelgsbase);
kvm_msr_entry_add(cpu, MSR_FMASK, env->fmask);
kvm_msr_entry_add(cpu, MSR_LSTAR, env->lstar);
+ if (env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_FRED) {
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP0, env->fred_rsp0);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP1, env->fred_rsp1);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP2, env->fred_rsp2);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP3, env->fred_rsp3);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_STKLVLS, env->fred_stklvls);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP0, env->fred_ssp0);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP1, env->fred_ssp1);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP2, env->fred_ssp2);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP3, env->fred_ssp3);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_CONFIG, env->fred_config);
+ }
}
#endif
@@ -3897,6 +3909,18 @@ static int kvm_get_msrs(X86CPU *cpu)
kvm_msr_entry_add(cpu, MSR_KERNELGSBASE, 0);
kvm_msr_entry_add(cpu, MSR_FMASK, 0);
kvm_msr_entry_add(cpu, MSR_LSTAR, 0);
+ if (env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_FRED) {
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP0, 0);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP1, 0);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP2, 0);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP3, 0);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_STKLVLS, 0);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP0, 0);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP1, 0);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP2, 0);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP3, 0);
+ kvm_msr_entry_add(cpu, MSR_IA32_FRED_CONFIG, 0);
+ }
}
#endif
kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, 0);
@@ -4118,6 +4142,36 @@ static int kvm_get_msrs(X86CPU *cpu)
case MSR_LSTAR:
env->lstar = msrs[i].data;
break;
+ case MSR_IA32_FRED_RSP0:
+ env->fred_rsp0 = msrs[i].data;
+ break;
+ case MSR_IA32_FRED_RSP1:
+ env->fred_rsp1 = msrs[i].data;
+ break;
+ case MSR_IA32_FRED_RSP2:
+ env->fred_rsp2 = msrs[i].data;
+ break;
+ case MSR_IA32_FRED_RSP3:
+ env->fred_rsp3 = msrs[i].data;
+ break;
+ case MSR_IA32_FRED_STKLVLS:
+ env->fred_stklvls = msrs[i].data;
+ break;
+ case MSR_IA32_FRED_SSP0:
+ env->fred_ssp0 = msrs[i].data;
+ break;
+ case MSR_IA32_FRED_SSP1:
+ env->fred_ssp1 = msrs[i].data;
+ break;
+ case MSR_IA32_FRED_SSP2:
+ env->fred_ssp2 = msrs[i].data;
+ break;
+ case MSR_IA32_FRED_SSP3:
+ env->fred_ssp3 = msrs[i].data;
+ break;
+ case MSR_IA32_FRED_CONFIG:
+ env->fred_config = msrs[i].data;
+ break;
#endif
case MSR_IA32_TSC:
env->tsc = msrs[i].data;
diff --git a/target/i386/machine.c b/target/i386/machine.c
index a1041ef828..695e402246 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -1544,6 +1544,34 @@ static const VMStateDescription vmstate_msr_xfd = {
};
#ifdef TARGET_X86_64
+static bool intel_fred_msrs_needed(void *opaque)
+{
+ X86CPU *cpu = opaque;
+ CPUX86State *env = &cpu->env;
+
+ return !!(env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_FRED);
+}
+
+static const VMStateDescription vmstate_msr_fred = {
+ .name = "cpu/fred",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = intel_fred_msrs_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64(env.fred_rsp0, X86CPU),
+ VMSTATE_UINT64(env.fred_rsp1, X86CPU),
+ VMSTATE_UINT64(env.fred_rsp2, X86CPU),
+ VMSTATE_UINT64(env.fred_rsp3, X86CPU),
+ VMSTATE_UINT64(env.fred_stklvls, X86CPU),
+ VMSTATE_UINT64(env.fred_ssp0, X86CPU),
+ VMSTATE_UINT64(env.fred_ssp1, X86CPU),
+ VMSTATE_UINT64(env.fred_ssp2, X86CPU),
+ VMSTATE_UINT64(env.fred_ssp3, X86CPU),
+ VMSTATE_UINT64(env.fred_config, X86CPU),
+ VMSTATE_END_OF_LIST()
+ }
+ };
+
static bool amx_xtile_needed(void *opaque)
{
X86CPU *cpu = opaque;
@@ -1747,6 +1775,7 @@ const VMStateDescription vmstate_x86_cpu = {
&vmstate_pdptrs,
&vmstate_msr_xfd,
#ifdef TARGET_X86_64
+ &vmstate_msr_fred,
&vmstate_amx_xtile,
#endif
&vmstate_arch_lbr,
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread