diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2020-02-12 19:22:21 -0800 |
---|---|---|
committer | Laurent Vivier <laurent@vivier.eu> | 2020-03-26 08:08:54 +0100 |
commit | b26491b4d4f829fa4326d1ec2eea165a37bc6b3c (patch) | |
tree | 1e0b094b99e80fe3819bf81ee392f41f06dc1d37 /target | |
parent | acf768a904396b4a4b5fdfcb566843379dc8feb0 (diff) |
linux-user/i386: Emulate x86_64 vsyscalls
Notice the magic page during translate, much like we already
do for the arm32 commpage. At runtime, raise an exception to
return cpu_loop for emulation.
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20200213032223.14643-4-richard.henderson@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Diffstat (limited to 'target')
-rw-r--r-- | target/i386/cpu.h | 7 | ||||
-rw-r--r-- | target/i386/translate.c | 14 |
2 files changed, 20 insertions, 1 deletions
diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 49ecc23104..9af1b0c12e 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1003,6 +1003,7 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; #define EXCP_VMEXIT 0x100 /* only for system emulation */ #define EXCP_SYSCALL 0x101 /* only for user emulation */ +#define EXCP_VSYSCALL 0x102 /* only for user emulation */ /* i386-specific interrupt pending bits. */ #define CPU_INTERRUPT_POLL CPU_INTERRUPT_TGT_EXT_1 @@ -2218,4 +2219,10 @@ static inline bool hyperv_feat_enabled(X86CPU *cpu, int feat) return !!(cpu->hyperv_features & BIT(feat)); } +#if defined(TARGET_X86_64) && \ + defined(CONFIG_USER_ONLY) && \ + defined(CONFIG_LINUX) +# define TARGET_VSYSCALL_PAGE (UINT64_C(-10) << 20) +#endif + #endif /* I386_CPU_H */ diff --git a/target/i386/translate.c b/target/i386/translate.c index d9af8f4078..5e5dbb41b0 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -8555,7 +8555,19 @@ static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) { DisasContext *dc = container_of(dcbase, DisasContext, base); - target_ulong pc_next = disas_insn(dc, cpu); + target_ulong pc_next; + +#ifdef TARGET_VSYSCALL_PAGE + /* + * Detect entry into the vsyscall page and invoke the syscall. + */ + if ((dc->base.pc_next & TARGET_PAGE_MASK) == TARGET_VSYSCALL_PAGE) { + gen_exception(dc, EXCP_VSYSCALL, dc->base.pc_next); + return; + } +#endif + + pc_next = disas_insn(dc, cpu); if (dc->tf || (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) { /* if single step mode, we generate only one instruction and |