diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2023-06-20 16:49:35 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2023-06-29 10:49:43 +0200 |
commit | 40a205da415e9c10ff02505078700e14ead77092 (patch) | |
tree | 3b55730d2d0541dcecddbcfc39d40e58744a2b4f /target | |
parent | d903259dd2dbe40e007db1724dd072c5e210b3f4 (diff) | |
download | qemu-40a205da415e9c10ff02505078700e14ead77092.zip qemu-40a205da415e9c10ff02505078700e14ead77092.tar.gz qemu-40a205da415e9c10ff02505078700e14ead77092.tar.bz2 |
target/i386: emulate 64-bit ring 0 for linux-user if LM feature is set
32-bit binaries can run on a long mode processor even if the kernel
is 64-bit, of course, and this can have slightly different behavior;
for example, SYSCALL is allowed on Intel processors.
Allow reporting LM to programs running under user mode emulation,
so that "-cpu" can be used with named CPU models even for qemu-i386
and even without disabling LM by hand.
Fortunately, most of the runtime code in QEMU has to depend on HF_LMA_MASK
or on HF_CS64_MASK (which is anyway false for qemu-i386's 32-bit code
segment) rather than TARGET_X86_64, therefore all that is needed is an
update of linux-user's ring 0 setup.
Fixes: https://gitlab.com/qemu-project/qemu/-/issues/1534
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'target')
-rw-r--r-- | target/i386/cpu.c | 15 | ||||
-rw-r--r-- | target/i386/tcg/translate.c | 6 |
2 files changed, 17 insertions, 4 deletions
diff --git a/target/i386/cpu.c b/target/i386/cpu.c index a3ddd1b..b5688ca 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -666,7 +666,10 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, * and therefore using the 32-bit ABI; the CPU itself might be 64-bit * but again the difference is only visible in kernel mode. */ -#if defined CONFIG_USER_ONLY +#if defined CONFIG_LINUX_USER +#define CPUID_EXT2_KERNEL_FEATURES (CPUID_EXT2_LM | CPUID_EXT2_FFXSR) +#elif defined CONFIG_USER_ONLY +/* FIXME: Long mode not yet supported for i386 bsd-user */ #define CPUID_EXT2_KERNEL_FEATURES CPUID_EXT2_FFXSR #else #define CPUID_EXT2_KERNEL_FEATURES 0 @@ -5539,7 +5542,15 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, } #ifndef TARGET_X86_64 if (w == FEAT_8000_0001_EDX) { - r &= ~CPUID_EXT2_LM; + /* + * 32-bit TCG can emulate 64-bit compatibility mode. If there is no + * way for userspace to get out of its 32-bit jail, we can leave + * the LM bit set. + */ + uint32_t unavail = tcg_enabled() + ? CPUID_EXT2_LM & ~CPUID_EXT2_KERNEL_FEATURES + : CPUID_EXT2_LM; + r &= ~unavail; } #endif if (migratable_only) { diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 28cb3fb..90c7b32 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -173,12 +173,14 @@ typedef struct DisasContext { #endif #if !defined(TARGET_X86_64) #define CODE64(S) false -#define LMA(S) false #elif defined(CONFIG_USER_ONLY) #define CODE64(S) true -#define LMA(S) true #else #define CODE64(S) (((S)->flags & HF_CS64_MASK) != 0) +#endif +#if defined(CONFIG_SOFTMMU) && !defined(TARGET_X86_64) +#define LMA(S) false +#else #define LMA(S) (((S)->flags & HF_LMA_MASK) != 0) #endif |