* [PATCH v3 01/11] target/i386: fix INVD vmexit
2023-06-23 13:17 [PATCH v3 00/11] target/i386: add a few simple features Paolo Bonzini
@ 2023-06-23 13:17 ` Paolo Bonzini
2023-06-23 13:17 ` [PATCH v3 02/11] target/i386: TCG supports 3DNow! prefetch(w) Paolo Bonzini
` (9 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Paolo Bonzini @ 2023-06-23 13:17 UTC (permalink / raw)
To: qemu-devel; +Cc: richard.henderson
Due to a typo or perhaps a brain fart, the INVD vmexit was never generated.
Fix it (but not that fixing just the typo would break both INVD and WBINVD,
due to a case of two wrongs making a right).
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/translate.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 08c4cab73f1..0de068d4b79 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -6119,7 +6119,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
case 0x108: /* invd */
case 0x109: /* wbinvd */
if (check_cpl0(s)) {
- gen_svm_check_intercept(s, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
+ gen_svm_check_intercept(s, (b & 1) ? SVM_EXIT_WBINVD : SVM_EXIT_INVD);
/* nothing to do */
}
break;
--
2.41.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 02/11] target/i386: TCG supports 3DNow! prefetch(w)
2023-06-23 13:17 [PATCH v3 00/11] target/i386: add a few simple features Paolo Bonzini
2023-06-23 13:17 ` [PATCH v3 01/11] target/i386: fix INVD vmexit Paolo Bonzini
@ 2023-06-23 13:17 ` Paolo Bonzini
2023-06-23 13:17 ` [PATCH v3 03/11] target/i386: TCG supports RDSEED Paolo Bonzini
` (8 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Paolo Bonzini @ 2023-06-23 13:17 UTC (permalink / raw)
To: qemu-devel; +Cc: richard.henderson
The AMD prefetch(w) instructions have not been deprecated together with the rest
of 3DNow!, and in fact are even supported by newer Intel processor. Mark them
as supported by TCG, as it supports all of 3DNow!.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/cpu.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 1242bd541a5..ff3dcd02dcb 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -647,7 +647,8 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_PDPE1GB | \
TCG_EXT2_X86_64_FEATURES)
#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
- CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
+ CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A | \
+ CPUID_EXT3_3DNOWPREFETCH)
#define TCG_EXT4_FEATURES 0
#define TCG_SVM_FEATURES (CPUID_SVM_NPT | CPUID_SVM_VGIF | \
CPUID_SVM_SVME_ADDR_CHK)
--
2.41.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 03/11] target/i386: TCG supports RDSEED
2023-06-23 13:17 [PATCH v3 00/11] target/i386: add a few simple features Paolo Bonzini
2023-06-23 13:17 ` [PATCH v3 01/11] target/i386: fix INVD vmexit Paolo Bonzini
2023-06-23 13:17 ` [PATCH v3 02/11] target/i386: TCG supports 3DNow! prefetch(w) Paolo Bonzini
@ 2023-06-23 13:17 ` Paolo Bonzini
2023-06-23 13:17 ` [PATCH v3 04/11] target/i386: do not accept RDSEED if CPUID bit absent Paolo Bonzini
` (7 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Paolo Bonzini @ 2023-06-23 13:17 UTC (permalink / raw)
To: qemu-devel; +Cc: richard.henderson
TCG implements RDSEED, and in fact uses qcrypto_random_bytes which is
secure enough to match hardware behavior. Expose it to guests.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/cpu.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index ff3dcd02dcb..fc4246223d4 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -657,11 +657,10 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT | \
CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_FSGSBASE | \
- CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_AVX2)
+ CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_RDSEED)
/* missing:
CPUID_7_0_EBX_HLE
- CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
- CPUID_7_0_EBX_RDSEED */
+ CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM */
#define TCG_7_0_ECX_FEATURES (CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | \
/* CPUID_7_0_ECX_OSPKE is dynamic */ \
CPUID_7_0_ECX_LA57 | CPUID_7_0_ECX_PKS | CPUID_7_0_ECX_VAES)
--
2.41.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 04/11] target/i386: do not accept RDSEED if CPUID bit absent
2023-06-23 13:17 [PATCH v3 00/11] target/i386: add a few simple features Paolo Bonzini
` (2 preceding siblings ...)
2023-06-23 13:17 ` [PATCH v3 03/11] target/i386: TCG supports RDSEED Paolo Bonzini
@ 2023-06-23 13:17 ` Paolo Bonzini
2023-06-26 7:51 ` Richard Henderson
2023-06-23 13:17 ` [PATCH v3 05/11] target/i386: TCG supports XSAVEERPTR Paolo Bonzini
` (6 subsequent siblings)
10 siblings, 1 reply; 15+ messages in thread
From: Paolo Bonzini @ 2023-06-23 13:17 UTC (permalink / raw)
To: qemu-devel; +Cc: richard.henderson
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/translate.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 0de068d4b79..4ef45bbd71e 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3925,12 +3925,20 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
break;
case 7: /* RDSEED */
+ if (mod != 3 ||
+ (s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
+ !(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_RDSEED)) {
+ goto illegal_op;
+ }
+ goto do_rdrand;
+
case 6: /* RDRAND */
if (mod != 3 ||
(s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
!(s->cpuid_ext_features & CPUID_EXT_RDRAND)) {
goto illegal_op;
}
+ do_rdrand:
translator_io_start(&s->base);
gen_helper_rdrand(s->T0, cpu_env);
rm = (modrm & 7) | REX_B(s);
--
2.41.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 05/11] target/i386: TCG supports XSAVEERPTR
2023-06-23 13:17 [PATCH v3 00/11] target/i386: add a few simple features Paolo Bonzini
` (3 preceding siblings ...)
2023-06-23 13:17 ` [PATCH v3 04/11] target/i386: do not accept RDSEED if CPUID bit absent Paolo Bonzini
@ 2023-06-23 13:17 ` Paolo Bonzini
2023-06-23 13:17 ` [PATCH v3 06/11] target/i386: TCG supports WBNOINVD Paolo Bonzini
` (5 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Paolo Bonzini @ 2023-06-23 13:17 UTC (permalink / raw)
To: qemu-devel; +Cc: richard.henderson
XSAVEERPTR is actually a fix for an errata; TCG does not have the issue.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/cpu.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index fc4246223d4..bce0cb73e85 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -678,6 +678,8 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
#define TCG_SGX_12_0_EBX_FEATURES 0
#define TCG_SGX_12_1_EAX_FEATURES 0
+#define TCG_8000_0008_EBX CPUID_8000_0008_EBX_XSAVEERPTR
+
FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
[FEAT_1_EDX] = {
.type = CPUID_FEATURE_WORD,
@@ -939,7 +941,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
"amd-psfd", NULL, NULL, NULL,
},
.cpuid = { .eax = 0x80000008, .reg = R_EBX, },
- .tcg_features = 0,
+ .tcg_features = TCG_8000_0008_EBX,
.unmigratable_flags = 0,
},
[FEAT_8000_0021_EAX] = {
--
2.41.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 06/11] target/i386: TCG supports WBNOINVD
2023-06-23 13:17 [PATCH v3 00/11] target/i386: add a few simple features Paolo Bonzini
` (4 preceding siblings ...)
2023-06-23 13:17 ` [PATCH v3 05/11] target/i386: TCG supports XSAVEERPTR Paolo Bonzini
@ 2023-06-23 13:17 ` Paolo Bonzini
2023-06-23 13:17 ` [PATCH v3 07/11] target/i386: Intel only supports SYSCALL/SYSRET in long mode Paolo Bonzini
` (4 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Paolo Bonzini @ 2023-06-23 13:17 UTC (permalink / raw)
To: qemu-devel; +Cc: richard.henderson
WBNOINVD is the same as INVD or WBINVD as far as TCG is concerned,
since there is no cache in TCG and therefore no invalidation side effect
in WBNOINVD.
With respect to SVM emulation, processors that do not support WBNOINVD
will ignore the prefix and treat it as WBINVD, while those that support
it will generate exactly the same vmexit.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/cpu.c | 3 ++-
target/i386/tcg/translate.c | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index bce0cb73e85..695e01582bf 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -678,7 +678,8 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
#define TCG_SGX_12_0_EBX_FEATURES 0
#define TCG_SGX_12_1_EAX_FEATURES 0
-#define TCG_8000_0008_EBX CPUID_8000_0008_EBX_XSAVEERPTR
+#define TCG_8000_0008_EBX (CPUID_8000_0008_EBX_XSAVEERPTR | \
+ CPUID_8000_0008_EBX_WBNOINVD)
FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
[FEAT_1_EDX] = {
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 4ef45bbd71e..b2e2dccb84f 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -6125,7 +6125,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
break;
case 0x108: /* invd */
- case 0x109: /* wbinvd */
+ case 0x109: /* wbinvd; wbnoinvd with REPZ prefix */
if (check_cpl0(s)) {
gen_svm_check_intercept(s, (b & 1) ? SVM_EXIT_WBINVD : SVM_EXIT_INVD);
/* nothing to do */
--
2.41.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 07/11] target/i386: Intel only supports SYSCALL/SYSRET in long mode
2023-06-23 13:17 [PATCH v3 00/11] target/i386: add a few simple features Paolo Bonzini
` (5 preceding siblings ...)
2023-06-23 13:17 ` [PATCH v3 06/11] target/i386: TCG supports WBNOINVD Paolo Bonzini
@ 2023-06-23 13:17 ` Paolo Bonzini
2023-06-23 13:17 ` [PATCH v3 08/11] target/i386: AMD only supports SYSENTER/SYSEXIT in 32-bit mode Paolo Bonzini
` (3 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Paolo Bonzini @ 2023-06-23 13:17 UTC (permalink / raw)
To: qemu-devel; +Cc: richard.henderson
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/cpu.c | 4 ++++
target/i386/tcg/translate.c | 9 ++++++++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 695e01582bf..978d24b5ec7 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6238,6 +6238,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*ecx |= 1 << 1; /* CmpLegacy bit */
}
}
+ if (tcg_enabled() && env->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 &&
+ !(env->hflags & HF_LMA_MASK)) {
+ *edx &= ~CPUID_EXT2_SYSCALL;
+ }
break;
case 0x80000002:
case 0x80000003:
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index b2e2dccb84f..ed4016f554b 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -5692,7 +5692,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
break;
#ifdef TARGET_X86_64
case 0x105: /* syscall */
- /* XXX: is it usable in real mode ? */
+ /* For Intel SYSCALL is only valid in long mode */
+ if (!LMA(s) && env->cpuid_vendor1 == CPUID_VENDOR_INTEL_1) {
+ goto illegal_op;
+ }
gen_update_cc_op(s);
gen_update_eip_cur(s);
gen_helper_syscall(cpu_env, cur_insn_len_i32(s));
@@ -5702,6 +5705,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_eob_worker(s, false, true);
break;
case 0x107: /* sysret */
+ /* For Intel SYSRET is only valid in long mode */
+ if (!LMA(s) && env->cpuid_vendor1 == CPUID_VENDOR_INTEL_1) {
+ goto illegal_op;
+ }
if (!PE(s)) {
gen_exception_gpf(s);
} else {
--
2.41.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 08/11] target/i386: AMD only supports SYSENTER/SYSEXIT in 32-bit mode
2023-06-23 13:17 [PATCH v3 00/11] target/i386: add a few simple features Paolo Bonzini
` (6 preceding siblings ...)
2023-06-23 13:17 ` [PATCH v3 07/11] target/i386: Intel only supports SYSCALL/SYSRET in long mode Paolo Bonzini
@ 2023-06-23 13:17 ` Paolo Bonzini
2023-06-26 7:53 ` Richard Henderson
2023-06-23 13:17 ` [PATCH v3 09/11] target/i386: sysret and sysexit are privileged Paolo Bonzini
` (2 subsequent siblings)
10 siblings, 1 reply; 15+ messages in thread
From: Paolo Bonzini @ 2023-06-23 13:17 UTC (permalink / raw)
To: qemu-devel; +Cc: richard.henderson
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/translate.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index ed4016f554b..a20b5af71e7 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -5669,9 +5669,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
s->base.is_jmp = DISAS_NORETURN;
break;
case 0x134: /* sysenter */
- /* For Intel SYSENTER is valid on 64-bit */
- if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
+ /* For AMD SYSENTER is not valid in long mode */
+ if (LMA(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
goto illegal_op;
+ }
if (!PE(s)) {
gen_exception_gpf(s);
} else {
@@ -5680,9 +5681,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
break;
case 0x135: /* sysexit */
- /* For Intel SYSEXIT is valid on 64-bit */
- if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
+ /* For AMD SYSEXIT is not valid in long mode */
+ if (LMA(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
goto illegal_op;
+ }
if (!PE(s)) {
gen_exception_gpf(s);
} else {
--
2.41.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v3 08/11] target/i386: AMD only supports SYSENTER/SYSEXIT in 32-bit mode
2023-06-23 13:17 ` [PATCH v3 08/11] target/i386: AMD only supports SYSENTER/SYSEXIT in 32-bit mode Paolo Bonzini
@ 2023-06-26 7:53 ` Richard Henderson
0 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2023-06-26 7:53 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel
On 6/23/23 15:17, Paolo Bonzini wrote:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> target/i386/tcg/translate.c | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
I guess we have no other vendors except Intel and AMD...
Acked-by: Richard Henderson <richard.henderson@linaro.org>
r~
>
> diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
> index ed4016f554b..a20b5af71e7 100644
> --- a/target/i386/tcg/translate.c
> +++ b/target/i386/tcg/translate.c
> @@ -5669,9 +5669,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
> s->base.is_jmp = DISAS_NORETURN;
> break;
> case 0x134: /* sysenter */
> - /* For Intel SYSENTER is valid on 64-bit */
> - if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
> + /* For AMD SYSENTER is not valid in long mode */
> + if (LMA(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
> goto illegal_op;
> + }
> if (!PE(s)) {
> gen_exception_gpf(s);
> } else {
> @@ -5680,9 +5681,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
> }
> break;
> case 0x135: /* sysexit */
> - /* For Intel SYSEXIT is valid on 64-bit */
> - if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
> + /* For AMD SYSEXIT is not valid in long mode */
> + if (LMA(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
> goto illegal_op;
> + }
> if (!PE(s)) {
> gen_exception_gpf(s);
> } else {
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v3 09/11] target/i386: sysret and sysexit are privileged
2023-06-23 13:17 [PATCH v3 00/11] target/i386: add a few simple features Paolo Bonzini
` (7 preceding siblings ...)
2023-06-23 13:17 ` [PATCH v3 08/11] target/i386: AMD only supports SYSENTER/SYSEXIT in 32-bit mode Paolo Bonzini
@ 2023-06-23 13:17 ` Paolo Bonzini
2023-06-23 13:17 ` [PATCH v3 10/11] target/i386: implement RDPID in TCG Paolo Bonzini
2023-06-23 13:17 ` [PATCH v3 11/11] target/i386: implement SYSCALL/SYSRET in 32-bit emulators Paolo Bonzini
10 siblings, 0 replies; 15+ messages in thread
From: Paolo Bonzini @ 2023-06-23 13:17 UTC (permalink / raw)
To: qemu-devel; +Cc: richard.henderson
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/translate.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index a20b5af71e7..66800392bb9 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -5685,7 +5685,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (LMA(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
goto illegal_op;
}
- if (!PE(s)) {
+ if (!PE(s) || CPL(s) != 0) {
gen_exception_gpf(s);
} else {
gen_helper_sysexit(cpu_env, tcg_constant_i32(dflag - 1));
@@ -5711,7 +5711,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (!LMA(s) && env->cpuid_vendor1 == CPUID_VENDOR_INTEL_1) {
goto illegal_op;
}
- if (!PE(s)) {
+ if (!PE(s) || CPL(s) != 0) {
gen_exception_gpf(s);
} else {
gen_helper_sysret(cpu_env, tcg_constant_i32(dflag - 1));
--
2.41.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 10/11] target/i386: implement RDPID in TCG
2023-06-23 13:17 [PATCH v3 00/11] target/i386: add a few simple features Paolo Bonzini
` (8 preceding siblings ...)
2023-06-23 13:17 ` [PATCH v3 09/11] target/i386: sysret and sysexit are privileged Paolo Bonzini
@ 2023-06-23 13:17 ` Paolo Bonzini
2023-06-23 13:17 ` [PATCH v3 11/11] target/i386: implement SYSCALL/SYSRET in 32-bit emulators Paolo Bonzini
10 siblings, 0 replies; 15+ messages in thread
From: Paolo Bonzini @ 2023-06-23 13:17 UTC (permalink / raw)
To: qemu-devel; +Cc: richard.henderson
RDPID corresponds to a RDMSR(TSC_AUX); however, it is unprivileged
so for user-mode emulation we must provide the value that the kernel
places in the MSR. For Linux, it is a combination of the current CPU
and the current NUMA node, both of which can be retrieved with getcpu(2).
Also try sched_getcpu(), which might be there on the BSDs. If there is
no portable way to retrieve the current CPU id from userspace, return 0.
RDTSCP is reimplemented as RDTSC + RDPID ECX; the differences in terms
of serializability are not relevant to QEMU.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
meson.build | 2 ++
target/i386/cpu.c | 10 +++++++++-
target/i386/helper.h | 2 +-
target/i386/tcg/misc_helper.c | 21 +++++++++++++++------
target/i386/tcg/translate.c | 24 +++++++++++++++++++-----
5 files changed, 46 insertions(+), 13 deletions(-)
diff --git a/meson.build b/meson.build
index 6ef78ea278b..3e3d38badb0 100644
--- a/meson.build
+++ b/meson.build
@@ -2232,6 +2232,8 @@ config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
+config_host_data.set('CONFIG_GETCPU', cc.has_function('getcpu', prefix: gnu_source_prefix))
+config_host_data.set('CONFIG_SCHED_GETCPU', cc.has_function('sched_getcpu', prefix: '#include <sched.h>'))
# Note that we need to specify prefix: here to avoid incorrectly
# thinking that Windows has posix_memalign()
config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 978d24b5ec7..4d52e612ac7 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -661,9 +661,17 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
/* missing:
CPUID_7_0_EBX_HLE
CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM */
+
+#if defined CONFIG_SOFTMMU || defined CONFIG_LINUX
+#define TCG_7_0_ECX_RDPID CPUID_7_0_ECX_RDPID
+#else
+#define TCG_7_0_ECX_RDPID 0
+#endif
#define TCG_7_0_ECX_FEATURES (CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | \
/* CPUID_7_0_ECX_OSPKE is dynamic */ \
- CPUID_7_0_ECX_LA57 | CPUID_7_0_ECX_PKS | CPUID_7_0_ECX_VAES)
+ CPUID_7_0_ECX_LA57 | CPUID_7_0_ECX_PKS | CPUID_7_0_ECX_VAES | \
+ TCG_7_0_ECX_RDPID)
+
#define TCG_7_0_EDX_FEATURES CPUID_7_0_EDX_FSRM
#define TCG_7_1_EAX_FEATURES (CPUID_7_1_EAX_FZRM | CPUID_7_1_EAX_FSRS | \
CPUID_7_1_EAX_FSRC)
diff --git a/target/i386/helper.h b/target/i386/helper.h
index 48609c210b1..c93c1d6c8f5 100644
--- a/target/i386/helper.h
+++ b/target/i386/helper.h
@@ -69,8 +69,8 @@ DEF_HELPER_2(into, void, env, int)
DEF_HELPER_FLAGS_1(single_step, TCG_CALL_NO_WG, noreturn, env)
DEF_HELPER_1(rechecking_single_step, void, env)
DEF_HELPER_1(cpuid, void, env)
+DEF_HELPER_FLAGS_1(rdpid, TCG_CALL_NO_WG, tl, env)
DEF_HELPER_1(rdtsc, void, env)
-DEF_HELPER_1(rdtscp, void, env)
DEF_HELPER_FLAGS_1(rdpmc, TCG_CALL_NO_WG, noreturn, env)
#ifndef CONFIG_USER_ONLY
diff --git a/target/i386/tcg/misc_helper.c b/target/i386/tcg/misc_helper.c
index 5f7a3061ca5..868f36ab7f5 100644
--- a/target/i386/tcg/misc_helper.c
+++ b/target/i386/tcg/misc_helper.c
@@ -75,12 +75,6 @@ void helper_rdtsc(CPUX86State *env)
env->regs[R_EDX] = (uint32_t)(val >> 32);
}
-void helper_rdtscp(CPUX86State *env)
-{
- helper_rdtsc(env);
- env->regs[R_ECX] = (uint32_t)(env->tsc_aux);
-}
-
G_NORETURN void helper_rdpmc(CPUX86State *env)
{
if (((env->cr[4] & CR4_PCE_MASK) == 0 ) &&
@@ -137,3 +131,18 @@ void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val)
env->pkru = val;
tlb_flush(cs);
}
+
+target_ulong HELPER(rdpid)(CPUX86State *env)
+{
+#if defined CONFIG_SOFTMMU
+ return env->tsc_aux;
+#elif defined CONFIG_LINUX && defined CONFIG_GETCPU
+ unsigned cpu, node;
+ getcpu(&cpu, &node);
+ return (node << 12) | (cpu & 0xfff);
+#elif defined CONFIG_SCHED_GETCPU
+ return sched_getcpu();
+#else
+ return 0;
+#endif
+}
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 66800392bb9..a6c24241338 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3924,13 +3924,25 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_cmpxchg8b(s, env, modrm);
break;
- case 7: /* RDSEED */
+ case 7: /* RDSEED, RDPID with f3 prefix */
if (mod != 3 ||
- (s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
- !(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_RDSEED)) {
+ (s->prefix & (PREFIX_LOCK | PREFIX_REPNZ))) {
goto illegal_op;
}
- goto do_rdrand;
+ if (s->prefix & PREFIX_REPZ) {
+ if (!(s->cpuid_ext_features & CPUID_7_0_ECX_RDPID)) {
+ goto illegal_op;
+ }
+ gen_helper_rdpid(s->T0, cpu_env);
+ rm = (modrm & 7) | REX_B(s);
+ gen_op_mov_reg_v(s, dflag, rm, s->T0);
+ break;
+ } else {
+ if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_RDSEED)) {
+ goto illegal_op;
+ }
+ goto do_rdrand;
+ }
case 6: /* RDRAND */
if (mod != 3 ||
@@ -6125,7 +6137,9 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_update_cc_op(s);
gen_update_eip_cur(s);
translator_io_start(&s->base);
- gen_helper_rdtscp(cpu_env);
+ gen_helper_rdtsc(cpu_env);
+ gen_helper_rdpid(s->T0, cpu_env);
+ gen_op_mov_reg_v(s, dflag, R_ECX, s->T0);
break;
default:
--
2.41.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 11/11] target/i386: implement SYSCALL/SYSRET in 32-bit emulators
2023-06-23 13:17 [PATCH v3 00/11] target/i386: add a few simple features Paolo Bonzini
` (9 preceding siblings ...)
2023-06-23 13:17 ` [PATCH v3 10/11] target/i386: implement RDPID in TCG Paolo Bonzini
@ 2023-06-23 13:17 ` Paolo Bonzini
2023-06-26 7:56 ` Richard Henderson
10 siblings, 1 reply; 15+ messages in thread
From: Paolo Bonzini @ 2023-06-23 13:17 UTC (permalink / raw)
To: qemu-devel; +Cc: richard.henderson
AMD supports both 32-bit and 64-bit SYSCALL/SYSRET, but the TCG only
exposes it for 64-bit targets. For system emulation just reuse the
helper; for user-mode emulation the ABI is the same as "int $80".
The BSDs does not support any fast system call mechanism in 32-bit
mode so add to bsd-user the same stub that FreeBSD has for 64-bit
compatibility mode.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
bsd-user/i386/target_arch_cpu.h | 4 ++++
linux-user/i386/cpu_loop.c | 13 +++++++++----
target/i386/cpu.c | 4 ++--
target/i386/helper.h | 2 --
target/i386/tcg/seg_helper.c | 7 +++++--
target/i386/tcg/sysemu/seg_helper.c | 7 ++++---
target/i386/tcg/translate.c | 2 --
target/i386/tcg/user/seg_helper.c | 2 --
8 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/bsd-user/i386/target_arch_cpu.h b/bsd-user/i386/target_arch_cpu.h
index d792dc720f9..9bf2c4244b7 100644
--- a/bsd-user/i386/target_arch_cpu.h
+++ b/bsd-user/i386/target_arch_cpu.h
@@ -164,6 +164,10 @@ static inline void target_cpu_loop(CPUX86State *env)
}
break;
+ case EXCP_SYSCALL:
+ /* doesn't do anything */
+ break;
+
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c
index 2d0918a93ff..3283f08cd9c 100644
--- a/linux-user/i386/cpu_loop.c
+++ b/linux-user/i386/cpu_loop.c
@@ -211,6 +211,9 @@ void cpu_loop(CPUX86State *env)
switch(trapnr) {
case 0x80:
+#ifndef TARGET_X86_64
+ case EXCP_SYSCALL:
+#endif
/* linux syscall from int $0x80 */
ret = do_syscall(env,
env->regs[R_EAX],
@@ -227,9 +230,13 @@ void cpu_loop(CPUX86State *env)
env->regs[R_EAX] = ret;
}
break;
-#ifndef TARGET_ABI32
+#ifdef TARGET_X86_64
case EXCP_SYSCALL:
- /* linux syscall from syscall instruction */
+ /*
+ * linux syscall from syscall instruction. Note that x32 also
+ * uses the SYSCALL instruction and the 64-bit syscall table,
+ * so this uses TARGET_X86_64 not TARGET_ABI32.
+ */
ret = do_syscall(env,
env->regs[R_EAX],
env->regs[R_EDI],
@@ -245,8 +252,6 @@ void cpu_loop(CPUX86State *env)
env->regs[R_EAX] = ret;
}
break;
-#endif
-#ifdef TARGET_X86_64
case EXCP_VSYSCALL:
emulate_vsyscall(env);
break;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 4d52e612ac7..c0fb6b3ad92 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -637,7 +637,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER */
#ifdef TARGET_X86_64
-#define TCG_EXT2_X86_64_FEATURES (CPUID_EXT2_SYSCALL | CPUID_EXT2_LM)
+#define TCG_EXT2_X86_64_FEATURES CPUID_EXT2_LM
#else
#define TCG_EXT2_X86_64_FEATURES 0
#endif
@@ -645,7 +645,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
#define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \
CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_PDPE1GB | \
- TCG_EXT2_X86_64_FEATURES)
+ CPUID_EXT2_SYSCALL | TCG_EXT2_X86_64_FEATURES)
#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A | \
CPUID_EXT3_3DNOWPREFETCH)
diff --git a/target/i386/helper.h b/target/i386/helper.h
index c93c1d6c8f5..ac2b04abd63 100644
--- a/target/i386/helper.h
+++ b/target/i386/helper.h
@@ -51,10 +51,8 @@ DEF_HELPER_FLAGS_2(get_dr, TCG_CALL_NO_WG, tl, env, int)
DEF_HELPER_1(sysenter, void, env)
DEF_HELPER_2(sysexit, void, env, int)
-#ifdef TARGET_X86_64
DEF_HELPER_2(syscall, void, env, int)
DEF_HELPER_2(sysret, void, env, int)
-#endif
DEF_HELPER_FLAGS_2(pause, TCG_CALL_NO_WG, noreturn, env, int)
DEF_HELPER_FLAGS_3(raise_interrupt, TCG_CALL_NO_WG, noreturn, env, int, int)
DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, noreturn, env, int)
diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
index 03b58e94a2d..e8d19c65fdc 100644
--- a/target/i386/tcg/seg_helper.c
+++ b/target/i386/tcg/seg_helper.c
@@ -977,6 +977,7 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
e2);
env->eip = offset;
}
+#endif /* TARGET_X86_64 */
void helper_sysret(CPUX86State *env, int dflag)
{
@@ -990,6 +991,7 @@ void helper_sysret(CPUX86State *env, int dflag)
raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
}
selector = (env->star >> 48) & 0xffff;
+#ifdef TARGET_X86_64
if (env->hflags & HF_LMA_MASK) {
cpu_load_eflags(env, (uint32_t)(env->regs[11]), TF_MASK | AC_MASK
| ID_MASK | IF_MASK | IOPL_MASK | VM_MASK | RF_MASK |
@@ -1015,7 +1017,9 @@ void helper_sysret(CPUX86State *env, int dflag)
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
DESC_W_MASK | DESC_A_MASK);
- } else {
+ } else
+#endif
+ {
env->eflags |= IF_MASK;
cpu_x86_load_seg_cache(env, R_CS, selector | 3,
0, 0xffffffff,
@@ -1030,7 +1034,6 @@ void helper_sysret(CPUX86State *env, int dflag)
DESC_W_MASK | DESC_A_MASK);
}
}
-#endif /* TARGET_X86_64 */
/* real mode interrupt */
static void do_interrupt_real(CPUX86State *env, int intno, int is_int,
diff --git a/target/i386/tcg/sysemu/seg_helper.c b/target/i386/tcg/sysemu/seg_helper.c
index 2c9bd007adb..1cb5a0db45c 100644
--- a/target/i386/tcg/sysemu/seg_helper.c
+++ b/target/i386/tcg/sysemu/seg_helper.c
@@ -26,7 +26,6 @@
#include "tcg/helper-tcg.h"
#include "../seg_helper.h"
-#ifdef TARGET_X86_64
void helper_syscall(CPUX86State *env, int next_eip_addend)
{
int selector;
@@ -35,6 +34,7 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
}
selector = (env->star >> 32) & 0xffff;
+#ifdef TARGET_X86_64
if (env->hflags & HF_LMA_MASK) {
int code64;
@@ -61,7 +61,9 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
} else {
env->eip = env->cstar;
}
- } else {
+ } else
+#endif
+ {
env->regs[R_ECX] = (uint32_t)(env->eip + next_eip_addend);
env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
@@ -78,7 +80,6 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
env->eip = (uint32_t)env->star;
}
}
-#endif /* TARGET_X86_64 */
void handle_even_inj(CPUX86State *env, int intno, int is_int,
int error_code, int is_hw, int rm)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index a6c24241338..28cb3fb7f4b 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -5704,7 +5704,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
s->base.is_jmp = DISAS_EOB_ONLY;
}
break;
-#ifdef TARGET_X86_64
case 0x105: /* syscall */
/* For Intel SYSCALL is only valid in long mode */
if (!LMA(s) && env->cpuid_vendor1 == CPUID_VENDOR_INTEL_1) {
@@ -5738,7 +5737,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_eob_worker(s, false, true);
}
break;
-#endif
case 0x1a2: /* cpuid */
gen_update_cc_op(s);
gen_update_eip_cur(s);
diff --git a/target/i386/tcg/user/seg_helper.c b/target/i386/tcg/user/seg_helper.c
index 67481b0aa8e..c45f2ac2ba6 100644
--- a/target/i386/tcg/user/seg_helper.c
+++ b/target/i386/tcg/user/seg_helper.c
@@ -26,7 +26,6 @@
#include "tcg/helper-tcg.h"
#include "tcg/seg_helper.h"
-#ifdef TARGET_X86_64
void helper_syscall(CPUX86State *env, int next_eip_addend)
{
CPUState *cs = env_cpu(env);
@@ -36,7 +35,6 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
env->exception_next_eip = env->eip + next_eip_addend;
cpu_loop_exit(cs);
}
-#endif /* TARGET_X86_64 */
/*
* fake user mode interrupt. is_int is TRUE if coming from the int
--
2.41.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v3 11/11] target/i386: implement SYSCALL/SYSRET in 32-bit emulators
2023-06-23 13:17 ` [PATCH v3 11/11] target/i386: implement SYSCALL/SYSRET in 32-bit emulators Paolo Bonzini
@ 2023-06-26 7:56 ` Richard Henderson
0 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2023-06-26 7:56 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel
On 6/23/23 15:17, Paolo Bonzini wrote:
> AMD supports both 32-bit and 64-bit SYSCALL/SYSRET, but the TCG only
> exposes it for 64-bit targets. For system emulation just reuse the
> helper; for user-mode emulation the ABI is the same as "int $80".
>
> The BSDs does not support any fast system call mechanism in 32-bit
> mode so add to bsd-user the same stub that FreeBSD has for 64-bit
> compatibility mode.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> bsd-user/i386/target_arch_cpu.h | 4 ++++
> linux-user/i386/cpu_loop.c | 13 +++++++++----
> target/i386/cpu.c | 4 ++--
> target/i386/helper.h | 2 --
> target/i386/tcg/seg_helper.c | 7 +++++--
> target/i386/tcg/sysemu/seg_helper.c | 7 ++++---
> target/i386/tcg/translate.c | 2 --
> target/i386/tcg/user/seg_helper.c | 2 --
> 8 files changed, 24 insertions(+), 17 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 15+ messages in thread