aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2020-02-12 19:22:21 -0800
committerLaurent Vivier <laurent@vivier.eu>2020-03-26 08:08:54 +0100
commitb26491b4d4f829fa4326d1ec2eea165a37bc6b3c (patch)
tree1e0b094b99e80fe3819bf81ee392f41f06dc1d37 /target
parentacf768a904396b4a4b5fdfcb566843379dc8feb0 (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.h7
-rw-r--r--target/i386/translate.c14
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