QEMU-Devel Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/3] linux-user: Implement x86_64 vsyscalls
@ 2020-01-14 21:09 Richard Henderson
  2020-01-14 21:09 ` [PATCH 1/3] target/i386: Renumber EXCP_SYSCALL Richard Henderson
                   ` (7 more replies)
  0 siblings, 8 replies; 21+ messages in thread
From: Richard Henderson @ 2020-01-14 21:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, riku.voipio, laurent, peter.maydell

The x86_64 abi has a legacy vsyscall page.  The kernel folk
have been trying to deprecate this since at least v3.1, but

(1) We don't implement the vdso that replaces vsyscalls,
(2) As of v5.5, the vsyscall page is still enabled by default.

This lack is affecting Peter's linux-user testing.

The dependency is not obvious because Peter is running the tests
on x86_64, so the host is providing a vsyscall page to qemu.

Because of how user-only memory operations are handled, with no
validation of guest vs host pages, so long as qemu chooses to
run with guest_base == 0, the guest may Just So Happen to read
the host's vsyscall page.

Complicating this, new OS releases may use a kernel configured
with CONFIG_LEGACY_VSYSCALL_XONLY=y, which means the the vsyscall
page cannot be read, only executed.  Which means that the guest
then cannot read the host vsyscall page during translation and
will SIGSEGV.

Exactly which of these many variables is affecting Peter's testing
with Ubuntu 18.04 of my TCG merge, I'm not exactly sure.  I suspect
that it is the change to drop the textseg_addr adjustment to user-only
static binaries.  IIRC bionic does not support -static-pie, which is
the preferred replacement.  This could mean that the host and guest
binaries overlap, which leads to guest_base != 0.

I vaguely remember someone (Paolo?) implementing something like
this many years ago, but clearly it never got merged.

In any case, this emulation has been missing for too long.


r~


Richard Henderson (3):
  target/i386: Renumber EXCP_SYSCALL
  linux-user/i386: Split out gen_signal
  linux-user/i386: Emulate x86_64 vsyscalls

 target/i386/cpu.h          |   6 +-
 linux-user/i386/cpu_loop.c | 197 ++++++++++++++++++++++++++-----------
 target/i386/translate.c    |  16 ++-
 3 files changed, 155 insertions(+), 64 deletions(-)

-- 
2.20.1



^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 1/3] target/i386: Renumber EXCP_SYSCALL
  2020-01-14 21:09 [PATCH 0/3] linux-user: Implement x86_64 vsyscalls Richard Henderson
@ 2020-01-14 21:09 ` Richard Henderson
  2020-01-15  7:22   ` Philippe Mathieu-Daudé
  2020-01-15  9:55   ` Alex Bennée
  2020-01-14 21:09 ` [PATCH 2/3] linux-user/i386: Split out gen_signal Richard Henderson
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 21+ messages in thread
From: Richard Henderson @ 2020-01-14 21:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, riku.voipio, laurent, peter.maydell

We are not short of numbers for EXCP_*.  There is no need to confuse things
by having EXCP_VMEXIT and EXCP_SYSCALL overlap, even though the former is
only used for system mode and the latter is only used for user mode.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/i386/cpu.h | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 594326a794..164d038d1f 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -998,9 +998,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
 #define EXCP11_ALGN	17
 #define EXCP12_MCHK	18
 
-#define EXCP_SYSCALL    0x100 /* only happens in user only emulation
-                                 for syscall instruction */
-#define EXCP_VMEXIT     0x100
+#define EXCP_VMEXIT     0x100 /* only for system emulation */
+#define EXCP_SYSCALL    0x101 /* only for user emulation */
 
 /* i386-specific interrupt pending bits.  */
 #define CPU_INTERRUPT_POLL      CPU_INTERRUPT_TGT_EXT_1
-- 
2.20.1



^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 2/3] linux-user/i386: Split out gen_signal
  2020-01-14 21:09 [PATCH 0/3] linux-user: Implement x86_64 vsyscalls Richard Henderson
  2020-01-14 21:09 ` [PATCH 1/3] target/i386: Renumber EXCP_SYSCALL Richard Henderson
@ 2020-01-14 21:09 ` Richard Henderson
  2020-01-15  7:22   ` Philippe Mathieu-Daudé
  2020-01-15  9:58   ` Alex Bennée
  2020-01-14 21:09 ` [PATCH 3/3] linux-user/i386: Emulate x86_64 vsyscalls Richard Henderson
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 21+ messages in thread
From: Richard Henderson @ 2020-01-14 21:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, riku.voipio, laurent, peter.maydell

This is a bit tidier than open-coding the 5 lines necessary
to initialize the target_siginfo_t.  In addition, this zeros
the remaining bytes of the target_siginfo_t, rather than
passing in garbage.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/i386/cpu_loop.c | 93 ++++++++++++++------------------------
 1 file changed, 33 insertions(+), 60 deletions(-)

diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c
index 024b6f4d58..e217cca5ee 100644
--- a/linux-user/i386/cpu_loop.c
+++ b/linux-user/i386/cpu_loop.c
@@ -81,13 +81,23 @@ static void set_idt(int n, unsigned int dpl)
 }
 #endif
 
+static void gen_signal(CPUX86State *env, int sig, int code, abi_ptr addr)
+{
+    target_siginfo_t info = {
+        .si_signo = sig,
+        .si_code = code,
+        ._sifields._sigfault._addr = addr
+    };
+
+    queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+}
+
 void cpu_loop(CPUX86State *env)
 {
     CPUState *cs = env_cpu(env);
     int trapnr;
     abi_ulong pc;
     abi_ulong ret;
-    target_siginfo_t info;
 
     for(;;) {
         cpu_exec_start(cs);
@@ -134,70 +144,45 @@ void cpu_loop(CPUX86State *env)
 #endif
         case EXCP0B_NOSEG:
         case EXCP0C_STACK:
-            info.si_signo = TARGET_SIGBUS;
-            info.si_errno = 0;
-            info.si_code = TARGET_SI_KERNEL;
-            info._sifields._sigfault._addr = 0;
-            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+            gen_signal(env, TARGET_SIGBUS, TARGET_SI_KERNEL, 0);
             break;
         case EXCP0D_GPF:
             /* XXX: potential problem if ABI32 */
 #ifndef TARGET_X86_64
             if (env->eflags & VM_MASK) {
                 handle_vm86_fault(env);
-            } else
-#endif
-            {
-                info.si_signo = TARGET_SIGSEGV;
-                info.si_errno = 0;
-                info.si_code = TARGET_SI_KERNEL;
-                info._sifields._sigfault._addr = 0;
-                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+                break;
             }
+#endif
+            gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
             break;
         case EXCP0E_PAGE:
-            info.si_signo = TARGET_SIGSEGV;
-            info.si_errno = 0;
-            if (!(env->error_code & 1))
-                info.si_code = TARGET_SEGV_MAPERR;
-            else
-                info.si_code = TARGET_SEGV_ACCERR;
-            info._sifields._sigfault._addr = env->cr[2];
-            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+            gen_signal(env, TARGET_SIGSEGV,
+                       (env->error_code & 1 ?
+                        TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR),
+                       env->cr[2]);
             break;
         case EXCP00_DIVZ:
 #ifndef TARGET_X86_64
             if (env->eflags & VM_MASK) {
                 handle_vm86_trap(env, trapnr);
-            } else
-#endif
-            {
-                /* division by zero */
-                info.si_signo = TARGET_SIGFPE;
-                info.si_errno = 0;
-                info.si_code = TARGET_FPE_INTDIV;
-                info._sifields._sigfault._addr = env->eip;
-                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+                break;
             }
+#endif
+            gen_signal(env, TARGET_SIGFPE, TARGET_FPE_INTDIV, env->eip);
             break;
         case EXCP01_DB:
         case EXCP03_INT3:
 #ifndef TARGET_X86_64
             if (env->eflags & VM_MASK) {
                 handle_vm86_trap(env, trapnr);
-            } else
+                break;
+            }
 #endif
-            {
-                info.si_signo = TARGET_SIGTRAP;
-                info.si_errno = 0;
-                if (trapnr == EXCP01_DB) {
-                    info.si_code = TARGET_TRAP_BRKPT;
-                    info._sifields._sigfault._addr = env->eip;
-                } else {
-                    info.si_code = TARGET_SI_KERNEL;
-                    info._sifields._sigfault._addr = 0;
-                }
-                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+            if (trapnr == EXCP01_DB) {
+                gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip);
+            } else {
+                gen_signal(env, TARGET_SIGTRAP, TARGET_SI_KERNEL, 0);
             }
             break;
         case EXCP04_INTO:
@@ -205,31 +190,19 @@ void cpu_loop(CPUX86State *env)
 #ifndef TARGET_X86_64
             if (env->eflags & VM_MASK) {
                 handle_vm86_trap(env, trapnr);
-            } else
-#endif
-            {
-                info.si_signo = TARGET_SIGSEGV;
-                info.si_errno = 0;
-                info.si_code = TARGET_SI_KERNEL;
-                info._sifields._sigfault._addr = 0;
-                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+                break;
             }
+#endif
+            gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
             break;
         case EXCP06_ILLOP:
-            info.si_signo = TARGET_SIGILL;
-            info.si_errno = 0;
-            info.si_code = TARGET_ILL_ILLOPN;
-            info._sifields._sigfault._addr = env->eip;
-            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+            gen_signal(env, TARGET_SIGILL, TARGET_ILL_ILLOPN, env->eip);
             break;
         case EXCP_INTERRUPT:
             /* just indicate that signals should be handled asap */
             break;
         case EXCP_DEBUG:
-            info.si_signo = TARGET_SIGTRAP;
-            info.si_errno = 0;
-            info.si_code = TARGET_TRAP_BRKPT;
-            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+            gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, 0);
             break;
         case EXCP_ATOMIC:
             cpu_exec_step_atomic(cs);
-- 
2.20.1



^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 3/3] linux-user/i386: Emulate x86_64 vsyscalls
  2020-01-14 21:09 [PATCH 0/3] linux-user: Implement x86_64 vsyscalls Richard Henderson
  2020-01-14 21:09 ` [PATCH 1/3] target/i386: Renumber EXCP_SYSCALL Richard Henderson
  2020-01-14 21:09 ` [PATCH 2/3] linux-user/i386: Split out gen_signal Richard Henderson
@ 2020-01-14 21:09 ` Richard Henderson
  2020-01-16 10:51   ` Alex Bennée
  2020-01-16 16:26   ` Alex Bennée
  2020-01-14 23:35 ` [PATCH 0/3] linux-user: Implement " Paolo Bonzini
                   ` (4 subsequent siblings)
  7 siblings, 2 replies; 21+ messages in thread
From: Richard Henderson @ 2020-01-14 21:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, riku.voipio, laurent, peter.maydell

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.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/i386/cpu.h          |   1 +
 linux-user/i386/cpu_loop.c | 104 +++++++++++++++++++++++++++++++++++++
 target/i386/translate.c    |  16 +++++-
 3 files changed, 120 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 164d038d1f..3fb2d2a986 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1000,6 +1000,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
diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c
index e217cca5ee..8b7c9f7337 100644
--- a/linux-user/i386/cpu_loop.c
+++ b/linux-user/i386/cpu_loop.c
@@ -92,6 +92,105 @@ static void gen_signal(CPUX86State *env, int sig, int code, abi_ptr addr)
     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
 }
 
+#ifdef TARGET_X86_64
+static bool write_ok_or_segv(CPUX86State *env, abi_ptr addr, size_t len)
+{
+    /*
+     * For all the vsyscalls, NULL means "don't write anything" not
+     * "write it at address 0".
+     */
+    if (addr == 0 || access_ok(VERIFY_WRITE, addr, len)) {
+        return true;
+    }
+
+    gen_signal(env, TARGET_SIGSEGV, TARGET_SEGV_MAPERR, addr);
+    return false;
+}
+
+/*
+ * Since v3.1, the kernel traps and emulates the vsyscall page.
+ * Entry points other than the official generate SIGSEGV.
+ */
+static void emulate_vsyscall(CPUX86State *env)
+{
+    int syscall;
+    abi_ulong ret;
+    uint64_t caller;
+
+    /*
+     * Validate the entry point.  We have already validated the page
+     * during translation, now verify the offset.
+     */
+    switch (env->eip & ~TARGET_PAGE_MASK) {
+    case 0x000:
+        syscall = TARGET_NR_gettimeofday;
+        break;
+    case 0x400:
+        syscall = TARGET_NR_time;
+        break;
+    case 0x800:
+        syscall = TARGET_NR_getcpu;
+        break;
+    default:
+    sigsegv:
+        /* Like force_sig(SIGSEGV).  */
+        gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
+        return;
+    }
+
+    /*
+     * Validate the return address.
+     * Note that the kernel treats this the same as an invalid entry point.
+     */
+    if (get_user_u64(caller, env->regs[R_ESP])) {
+        goto sigsegv;
+    }
+
+    /*
+     * Validate the the pointer arguments.
+     */
+    switch (syscall) {
+    case TARGET_NR_gettimeofday:
+        if (!write_ok_or_segv(env, env->regs[R_EDI],
+                              sizeof(struct target_timeval)) ||
+            !write_ok_or_segv(env, env->regs[R_ESI],
+                              sizeof(struct target_timezone))) {
+            return;
+        }
+        break;
+    case TARGET_NR_time:
+        if (!write_ok_or_segv(env, env->regs[R_EDI], sizeof(abi_long))) {
+            return;
+        }
+        break;
+    case TARGET_NR_getcpu:
+        if (!write_ok_or_segv(env, env->regs[R_EDI], sizeof(uint32_t)) ||
+            !write_ok_or_segv(env, env->regs[R_ESI], sizeof(uint32_t))) {
+            return;
+        }
+        break;
+    default:
+        g_assert_not_reached();
+    }
+
+    /*
+     * Perform the syscall.  None of the vsyscalls should need restarting,
+     * and all faults should have been caught above.
+     */
+    ret = do_syscall(env, syscall, env->regs[R_EDI], env->regs[R_ESI],
+                     env->regs[R_EDX], env->regs[10], env->regs[8],
+                     env->regs[9], 0, 0);
+    g_assert(ret != -TARGET_ERESTARTSYS);
+    g_assert(ret != -TARGET_QEMU_ESIGRETURN);
+    g_assert(ret != -TARGET_EFAULT);
+    env->regs[R_EAX] = ret;
+
+    /* Emulate a ret instruction to leave the vsyscall page.  */
+    env->eip = caller;
+    env->regs[R_ESP] += 8;
+}
+#endif
+
 void cpu_loop(CPUX86State *env)
 {
     CPUState *cs = env_cpu(env);
@@ -141,6 +240,11 @@ void cpu_loop(CPUX86State *env)
                 env->regs[R_EAX] = ret;
             }
             break;
+#endif
+#ifdef TARGET_X86_64
+        case EXCP_VSYSCALL:
+            emulate_vsyscall(env);
+            break;
 #endif
         case EXCP0B_NOSEG:
         case EXCP0C_STACK:
diff --git a/target/i386/translate.c b/target/i386/translate.c
index 7c99ef1385..391b4ef149 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8555,7 +8555,21 @@ 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;
+
+#if defined(TARGET_X86_64) && \
+    defined(CONFIG_USER_ONLY) && \
+    defined(CONFIG_LINUX)
+    /*
+     * Detect entry into the vsyscall page and invoke the syscall.
+     */
+    if ((dc->base.pc_next & TARGET_PAGE_MASK) == 0xffffffffff600000ull) {
+        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
-- 
2.20.1



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls
  2020-01-14 21:09 [PATCH 0/3] linux-user: Implement x86_64 vsyscalls Richard Henderson
                   ` (2 preceding siblings ...)
  2020-01-14 21:09 ` [PATCH 3/3] linux-user/i386: Emulate x86_64 vsyscalls Richard Henderson
@ 2020-01-14 23:35 ` " Paolo Bonzini
  2020-01-15  7:01 ` Laurent Desnogues
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Paolo Bonzini @ 2020-01-14 23:35 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: peter.maydell, riku.voipio, laurent

On 14/01/20 22:09, Richard Henderson wrote:
> I vaguely remember someone (Paolo?) implementing something like
> this many years ago, but clearly it never got merged.

Nope, certainly not me.

> In any case, this emulation has been missing for too long.
> 
> 
> r~
> 
> 
> Richard Henderson (3):
>   target/i386: Renumber EXCP_SYSCALL
>   linux-user/i386: Split out gen_signal
>   linux-user/i386: Emulate x86_64 vsyscalls
> 
>  target/i386/cpu.h          |   6 +-
>  linux-user/i386/cpu_loop.c | 197 ++++++++++++++++++++++++++-----------
>  target/i386/translate.c    |  16 ++-
>  3 files changed, 155 insertions(+), 64 deletions(-)
> 

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls
  2020-01-14 21:09 [PATCH 0/3] linux-user: Implement x86_64 vsyscalls Richard Henderson
                   ` (3 preceding siblings ...)
  2020-01-14 23:35 ` [PATCH 0/3] linux-user: Implement " Paolo Bonzini
@ 2020-01-15  7:01 ` Laurent Desnogues
  2020-01-15 10:14 ` Laurent Vivier
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Laurent Desnogues @ 2020-01-15  7:01 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Peter Maydell, Paolo Bonzini, Riku Voipio, qemu-devel, Laurent Vivier

On Tue, Jan 14, 2020 at 10:09 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
[...]
> I vaguely remember someone (Paolo?) implementing something like
> this many years ago, but clearly it never got merged.

That was me back in 2009:

https://lists.gnu.org/archive/html/qemu-devel/2009-07/msg00881.html

Glad it will finally get an official fix.

Thanks,

Laurent


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/3] linux-user/i386: Split out gen_signal
  2020-01-14 21:09 ` [PATCH 2/3] linux-user/i386: Split out gen_signal Richard Henderson
@ 2020-01-15  7:22   ` Philippe Mathieu-Daudé
  2020-01-15  9:58   ` Alex Bennée
  1 sibling, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-01-15  7:22 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: pbonzini, riku.voipio, laurent, peter.maydell

On 1/14/20 10:09 PM, Richard Henderson wrote:
> This is a bit tidier than open-coding the 5 lines necessary
> to initialize the target_siginfo_t.  In addition, this zeros
> the remaining bytes of the target_siginfo_t, rather than
> passing in garbage.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/i386/cpu_loop.c | 93 ++++++++++++++------------------------
>   1 file changed, 33 insertions(+), 60 deletions(-)
> 
> diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c
> index 024b6f4d58..e217cca5ee 100644
> --- a/linux-user/i386/cpu_loop.c
> +++ b/linux-user/i386/cpu_loop.c
> @@ -81,13 +81,23 @@ static void set_idt(int n, unsigned int dpl)
>   }
>   #endif
>   
> +static void gen_signal(CPUX86State *env, int sig, int code, abi_ptr addr)
> +{
> +    target_siginfo_t info = {
> +        .si_signo = sig,
> +        .si_code = code,
> +        ._sifields._sigfault._addr = addr
> +    };
> +
> +    queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +}
> +
>   void cpu_loop(CPUX86State *env)
>   {
>       CPUState *cs = env_cpu(env);
>       int trapnr;
>       abi_ulong pc;
>       abi_ulong ret;
> -    target_siginfo_t info;
>   
>       for(;;) {
>           cpu_exec_start(cs);
> @@ -134,70 +144,45 @@ void cpu_loop(CPUX86State *env)
>   #endif
>           case EXCP0B_NOSEG:
>           case EXCP0C_STACK:
> -            info.si_signo = TARGET_SIGBUS;
> -            info.si_errno = 0;
> -            info.si_code = TARGET_SI_KERNEL;
> -            info._sifields._sigfault._addr = 0;
> -            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +            gen_signal(env, TARGET_SIGBUS, TARGET_SI_KERNEL, 0);
>               break;
>           case EXCP0D_GPF:
>               /* XXX: potential problem if ABI32 */
>   #ifndef TARGET_X86_64
>               if (env->eflags & VM_MASK) {
>                   handle_vm86_fault(env);
> -            } else
> -#endif
> -            {
> -                info.si_signo = TARGET_SIGSEGV;
> -                info.si_errno = 0;
> -                info.si_code = TARGET_SI_KERNEL;
> -                info._sifields._sigfault._addr = 0;
> -                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +                break;
>               }
> +#endif
> +            gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
>               break;
>           case EXCP0E_PAGE:
> -            info.si_signo = TARGET_SIGSEGV;
> -            info.si_errno = 0;
> -            if (!(env->error_code & 1))
> -                info.si_code = TARGET_SEGV_MAPERR;
> -            else
> -                info.si_code = TARGET_SEGV_ACCERR;
> -            info._sifields._sigfault._addr = env->cr[2];
> -            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +            gen_signal(env, TARGET_SIGSEGV,
> +                       (env->error_code & 1 ?
> +                        TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR),
> +                       env->cr[2]);
>               break;
>           case EXCP00_DIVZ:
>   #ifndef TARGET_X86_64
>               if (env->eflags & VM_MASK) {
>                   handle_vm86_trap(env, trapnr);
> -            } else
> -#endif
> -            {
> -                /* division by zero */
> -                info.si_signo = TARGET_SIGFPE;
> -                info.si_errno = 0;
> -                info.si_code = TARGET_FPE_INTDIV;
> -                info._sifields._sigfault._addr = env->eip;
> -                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +                break;
>               }
> +#endif
> +            gen_signal(env, TARGET_SIGFPE, TARGET_FPE_INTDIV, env->eip);
>               break;
>           case EXCP01_DB:
>           case EXCP03_INT3:
>   #ifndef TARGET_X86_64
>               if (env->eflags & VM_MASK) {
>                   handle_vm86_trap(env, trapnr);
> -            } else
> +                break;
> +            }
>   #endif
> -            {
> -                info.si_signo = TARGET_SIGTRAP;
> -                info.si_errno = 0;
> -                if (trapnr == EXCP01_DB) {
> -                    info.si_code = TARGET_TRAP_BRKPT;
> -                    info._sifields._sigfault._addr = env->eip;
> -                } else {
> -                    info.si_code = TARGET_SI_KERNEL;
> -                    info._sifields._sigfault._addr = 0;
> -                }
> -                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +            if (trapnr == EXCP01_DB) {
> +                gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip);
> +            } else {
> +                gen_signal(env, TARGET_SIGTRAP, TARGET_SI_KERNEL, 0);
>               }
>               break;
>           case EXCP04_INTO:
> @@ -205,31 +190,19 @@ void cpu_loop(CPUX86State *env)
>   #ifndef TARGET_X86_64
>               if (env->eflags & VM_MASK) {
>                   handle_vm86_trap(env, trapnr);
> -            } else
> -#endif
> -            {
> -                info.si_signo = TARGET_SIGSEGV;
> -                info.si_errno = 0;
> -                info.si_code = TARGET_SI_KERNEL;
> -                info._sifields._sigfault._addr = 0;
> -                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +                break;
>               }
> +#endif
> +            gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
>               break;
>           case EXCP06_ILLOP:
> -            info.si_signo = TARGET_SIGILL;
> -            info.si_errno = 0;
> -            info.si_code = TARGET_ILL_ILLOPN;
> -            info._sifields._sigfault._addr = env->eip;
> -            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +            gen_signal(env, TARGET_SIGILL, TARGET_ILL_ILLOPN, env->eip);
>               break;
>           case EXCP_INTERRUPT:
>               /* just indicate that signals should be handled asap */
>               break;
>           case EXCP_DEBUG:
> -            info.si_signo = TARGET_SIGTRAP;
> -            info.si_errno = 0;
> -            info.si_code = TARGET_TRAP_BRKPT;
> -            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +            gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, 0);
>               break;
>           case EXCP_ATOMIC:
>               cpu_exec_step_atomic(cs);
> 

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] target/i386: Renumber EXCP_SYSCALL
  2020-01-14 21:09 ` [PATCH 1/3] target/i386: Renumber EXCP_SYSCALL Richard Henderson
@ 2020-01-15  7:22   ` Philippe Mathieu-Daudé
  2020-01-15  9:55   ` Alex Bennée
  1 sibling, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-01-15  7:22 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: pbonzini, riku.voipio, laurent, peter.maydell

On 1/14/20 10:09 PM, Richard Henderson wrote:
> We are not short of numbers for EXCP_*.  There is no need to confuse things
> by having EXCP_VMEXIT and EXCP_SYSCALL overlap, even though the former is
> only used for system mode and the latter is only used for user mode.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   target/i386/cpu.h | 5 ++---
>   1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 594326a794..164d038d1f 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -998,9 +998,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
>   #define EXCP11_ALGN	17
>   #define EXCP12_MCHK	18
>   
> -#define EXCP_SYSCALL    0x100 /* only happens in user only emulation
> -                                 for syscall instruction */
> -#define EXCP_VMEXIT     0x100
> +#define EXCP_VMEXIT     0x100 /* only for system emulation */
> +#define EXCP_SYSCALL    0x101 /* only for user emulation */
>   
>   /* i386-specific interrupt pending bits.  */
>   #define CPU_INTERRUPT_POLL      CPU_INTERRUPT_TGT_EXT_1
> 

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] target/i386: Renumber EXCP_SYSCALL
  2020-01-14 21:09 ` [PATCH 1/3] target/i386: Renumber EXCP_SYSCALL Richard Henderson
  2020-01-15  7:22   ` Philippe Mathieu-Daudé
@ 2020-01-15  9:55   ` Alex Bennée
  1 sibling, 0 replies; 21+ messages in thread
From: Alex Bennée @ 2020-01-15  9:55 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, pbonzini, riku.voipio, laurent, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> We are not short of numbers for EXCP_*.  There is no need to confuse things
> by having EXCP_VMEXIT and EXCP_SYSCALL overlap, even though the former is
> only used for system mode and the latter is only used for user mode.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target/i386/cpu.h | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 594326a794..164d038d1f 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -998,9 +998,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
>  #define EXCP11_ALGN	17
>  #define EXCP12_MCHK	18
>  
> -#define EXCP_SYSCALL    0x100 /* only happens in user only emulation
> -                                 for syscall instruction */
> -#define EXCP_VMEXIT     0x100
> +#define EXCP_VMEXIT     0x100 /* only for system emulation */
> +#define EXCP_SYSCALL    0x101 /* only for user emulation */
>  
>  /* i386-specific interrupt pending bits.  */
>  #define CPU_INTERRUPT_POLL      CPU_INTERRUPT_TGT_EXT_1


-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/3] linux-user/i386: Split out gen_signal
  2020-01-14 21:09 ` [PATCH 2/3] linux-user/i386: Split out gen_signal Richard Henderson
  2020-01-15  7:22   ` Philippe Mathieu-Daudé
@ 2020-01-15  9:58   ` Alex Bennée
  1 sibling, 0 replies; 21+ messages in thread
From: Alex Bennée @ 2020-01-15  9:58 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, pbonzini, riku.voipio, laurent, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> This is a bit tidier than open-coding the 5 lines necessary
> to initialize the target_siginfo_t.  In addition, this zeros
> the remaining bytes of the target_siginfo_t, rather than
> passing in garbage.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  linux-user/i386/cpu_loop.c | 93 ++++++++++++++------------------------
>  1 file changed, 33 insertions(+), 60 deletions(-)
>
> diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c
> index 024b6f4d58..e217cca5ee 100644
> --- a/linux-user/i386/cpu_loop.c
> +++ b/linux-user/i386/cpu_loop.c
> @@ -81,13 +81,23 @@ static void set_idt(int n, unsigned int dpl)
>  }
>  #endif
>  
> +static void gen_signal(CPUX86State *env, int sig, int code, abi_ptr addr)
> +{
> +    target_siginfo_t info = {
> +        .si_signo = sig,
> +        .si_code = code,
> +        ._sifields._sigfault._addr = addr
> +    };
> +
> +    queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +}
> +
>  void cpu_loop(CPUX86State *env)
>  {
>      CPUState *cs = env_cpu(env);
>      int trapnr;
>      abi_ulong pc;
>      abi_ulong ret;
> -    target_siginfo_t info;
>  
>      for(;;) {
>          cpu_exec_start(cs);
> @@ -134,70 +144,45 @@ void cpu_loop(CPUX86State *env)
>  #endif
>          case EXCP0B_NOSEG:
>          case EXCP0C_STACK:
> -            info.si_signo = TARGET_SIGBUS;
> -            info.si_errno = 0;
> -            info.si_code = TARGET_SI_KERNEL;
> -            info._sifields._sigfault._addr = 0;
> -            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +            gen_signal(env, TARGET_SIGBUS, TARGET_SI_KERNEL, 0);
>              break;
>          case EXCP0D_GPF:
>              /* XXX: potential problem if ABI32 */
>  #ifndef TARGET_X86_64
>              if (env->eflags & VM_MASK) {
>                  handle_vm86_fault(env);
> -            } else
> -#endif
> -            {
> -                info.si_signo = TARGET_SIGSEGV;
> -                info.si_errno = 0;
> -                info.si_code = TARGET_SI_KERNEL;
> -                info._sifields._sigfault._addr = 0;
> -                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +                break;
>              }
> +#endif
> +            gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
>              break;
>          case EXCP0E_PAGE:
> -            info.si_signo = TARGET_SIGSEGV;
> -            info.si_errno = 0;
> -            if (!(env->error_code & 1))
> -                info.si_code = TARGET_SEGV_MAPERR;
> -            else
> -                info.si_code = TARGET_SEGV_ACCERR;
> -            info._sifields._sigfault._addr = env->cr[2];
> -            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +            gen_signal(env, TARGET_SIGSEGV,
> +                       (env->error_code & 1 ?
> +                        TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR),
> +                       env->cr[2]);
>              break;
>          case EXCP00_DIVZ:
>  #ifndef TARGET_X86_64
>              if (env->eflags & VM_MASK) {
>                  handle_vm86_trap(env, trapnr);
> -            } else
> -#endif
> -            {
> -                /* division by zero */
> -                info.si_signo = TARGET_SIGFPE;
> -                info.si_errno = 0;
> -                info.si_code = TARGET_FPE_INTDIV;
> -                info._sifields._sigfault._addr = env->eip;
> -                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +                break;
>              }
> +#endif
> +            gen_signal(env, TARGET_SIGFPE, TARGET_FPE_INTDIV, env->eip);
>              break;
>          case EXCP01_DB:
>          case EXCP03_INT3:
>  #ifndef TARGET_X86_64
>              if (env->eflags & VM_MASK) {
>                  handle_vm86_trap(env, trapnr);
> -            } else
> +                break;
> +            }
>  #endif
> -            {
> -                info.si_signo = TARGET_SIGTRAP;
> -                info.si_errno = 0;
> -                if (trapnr == EXCP01_DB) {
> -                    info.si_code = TARGET_TRAP_BRKPT;
> -                    info._sifields._sigfault._addr = env->eip;
> -                } else {
> -                    info.si_code = TARGET_SI_KERNEL;
> -                    info._sifields._sigfault._addr = 0;
> -                }
> -                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +            if (trapnr == EXCP01_DB) {
> +                gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip);
> +            } else {
> +                gen_signal(env, TARGET_SIGTRAP, TARGET_SI_KERNEL, 0);
>              }
>              break;
>          case EXCP04_INTO:
> @@ -205,31 +190,19 @@ void cpu_loop(CPUX86State *env)
>  #ifndef TARGET_X86_64
>              if (env->eflags & VM_MASK) {
>                  handle_vm86_trap(env, trapnr);
> -            } else
> -#endif
> -            {
> -                info.si_signo = TARGET_SIGSEGV;
> -                info.si_errno = 0;
> -                info.si_code = TARGET_SI_KERNEL;
> -                info._sifields._sigfault._addr = 0;
> -                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +                break;
>              }
> +#endif
> +            gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
>              break;
>          case EXCP06_ILLOP:
> -            info.si_signo = TARGET_SIGILL;
> -            info.si_errno = 0;
> -            info.si_code = TARGET_ILL_ILLOPN;
> -            info._sifields._sigfault._addr = env->eip;
> -            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +            gen_signal(env, TARGET_SIGILL, TARGET_ILL_ILLOPN, env->eip);
>              break;
>          case EXCP_INTERRUPT:
>              /* just indicate that signals should be handled asap */
>              break;
>          case EXCP_DEBUG:
> -            info.si_signo = TARGET_SIGTRAP;
> -            info.si_errno = 0;
> -            info.si_code = TARGET_TRAP_BRKPT;
> -            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +            gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, 0);
>              break;
>          case EXCP_ATOMIC:
>              cpu_exec_step_atomic(cs);


-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls
  2020-01-14 21:09 [PATCH 0/3] linux-user: Implement x86_64 vsyscalls Richard Henderson
                   ` (4 preceding siblings ...)
  2020-01-15  7:01 ` Laurent Desnogues
@ 2020-01-15 10:14 ` Laurent Vivier
  2020-01-15 17:28   ` Richard Henderson
  2020-01-16 14:05 ` Alex Bennée
  2020-01-16 14:30 ` Alex Bennée
  7 siblings, 1 reply; 21+ messages in thread
From: Laurent Vivier @ 2020-01-15 10:14 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: pbonzini, riku.voipio, peter.maydell

Le 14/01/2020 à 22:09, Richard Henderson a écrit :
> The x86_64 abi has a legacy vsyscall page.  The kernel folk
> have been trying to deprecate this since at least v3.1, but
> 
> (1) We don't implement the vdso that replaces vsyscalls,
> (2) As of v5.5, the vsyscall page is still enabled by default.
> 
> This lack is affecting Peter's linux-user testing.
> 
> The dependency is not obvious because Peter is running the tests
> on x86_64, so the host is providing a vsyscall page to qemu.
> 
> Because of how user-only memory operations are handled, with no
> validation of guest vs host pages, so long as qemu chooses to
> run with guest_base == 0, the guest may Just So Happen to read
> the host's vsyscall page.
> 
> Complicating this, new OS releases may use a kernel configured
> with CONFIG_LEGACY_VSYSCALL_XONLY=y, which means the the vsyscall
> page cannot be read, only executed.  Which means that the guest
> then cannot read the host vsyscall page during translation and
> will SIGSEGV.
> 
> Exactly which of these many variables is affecting Peter's testing
> with Ubuntu 18.04 of my TCG merge, I'm not exactly sure.  I suspect
> that it is the change to drop the textseg_addr adjustment to user-only
> static binaries.  IIRC bionic does not support -static-pie, which is
> the preferred replacement.  This could mean that the host and guest
> binaries overlap, which leads to guest_base != 0.
> 
> I vaguely remember someone (Paolo?) implementing something like
> this many years ago, but clearly it never got merged.
> 
> In any case, this emulation has been missing for too long.
> 
> 
> r~
> 
> 
> Richard Henderson (3):
>   target/i386: Renumber EXCP_SYSCALL
>   linux-user/i386: Split out gen_signal
>   linux-user/i386: Emulate x86_64 vsyscalls
> 
>  target/i386/cpu.h          |   6 +-
>  linux-user/i386/cpu_loop.c | 197 ++++++++++++++++++++++++++-----------
>  target/i386/translate.c    |  16 ++-
>  3 files changed, 155 insertions(+), 64 deletions(-)
> 

Thank you Richard.

I'll take this series through the linux-user branch except if you prefer
to do the pull request yourself via another branch (x86 tcg?).

Thanks,
Laurent


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls
  2020-01-15 10:14 ` Laurent Vivier
@ 2020-01-15 17:28   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2020-01-15 17:28 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: pbonzini, riku.voipio, peter.maydell

On 1/15/20 12:14 AM, Laurent Vivier wrote:
> I'll take this series through the linux-user branch except if you prefer
> to do the pull request yourself via another branch (x86 tcg?).

Through the linux-user branch is the right way, I think.
Thanks,

r~


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/3] linux-user/i386: Emulate x86_64 vsyscalls
  2020-01-14 21:09 ` [PATCH 3/3] linux-user/i386: Emulate x86_64 vsyscalls Richard Henderson
@ 2020-01-16 10:51   ` Alex Bennée
  2020-01-16 16:26   ` Alex Bennée
  1 sibling, 0 replies; 21+ messages in thread
From: Alex Bennée @ 2020-01-16 10:51 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, pbonzini, riku.voipio, laurent, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> 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.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

So I've been trying to test this but have run into a number of
(unrelated) hurdles on the way on my system. I think I've eliminated
these patches but it might be a regression.

Does running /sbin/ldconfig work ok for you?

-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls
  2020-01-14 21:09 [PATCH 0/3] linux-user: Implement x86_64 vsyscalls Richard Henderson
                   ` (5 preceding siblings ...)
  2020-01-15 10:14 ` Laurent Vivier
@ 2020-01-16 14:05 ` Alex Bennée
  2020-01-16 19:37   ` Richard Henderson
  2020-01-16 14:30 ` Alex Bennée
  7 siblings, 1 reply; 21+ messages in thread
From: Alex Bennée @ 2020-01-16 14:05 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, pbonzini, riku.voipio, laurent, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> The x86_64 abi has a legacy vsyscall page.  The kernel folk
> have been trying to deprecate this since at least v3.1, but
>
> (1) We don't implement the vdso that replaces vsyscalls,
> (2) As of v5.5, the vsyscall page is still enabled by default.
>
> This lack is affecting Peter's linux-user testing.
>
> The dependency is not obvious because Peter is running the tests
> on x86_64, so the host is providing a vsyscall page to qemu.
>
> Because of how user-only memory operations are handled, with no
> validation of guest vs host pages, so long as qemu chooses to
> run with guest_base == 0, the guest may Just So Happen to read
> the host's vsyscall page.
>
> Complicating this, new OS releases may use a kernel configured
> with CONFIG_LEGACY_VSYSCALL_XONLY=y, which means the the vsyscall
> page cannot be read, only executed.  Which means that the guest
> then cannot read the host vsyscall page during translation and
> will SIGSEGV.
>
> Exactly which of these many variables is affecting Peter's testing
> with Ubuntu 18.04 of my TCG merge, I'm not exactly sure.  I suspect
> that it is the change to drop the textseg_addr adjustment to user-only
> static binaries.  IIRC bionic does not support -static-pie, which is
> the preferred replacement.  This could mean that the host and guest
> binaries overlap, which leads to guest_base != 0.
>
> I vaguely remember someone (Paolo?) implementing something like
> this many years ago, but clearly it never got merged.
>
> In any case, this emulation has been missing for too long.

It turns out the /sbin/ldconfig crash is a regression w.r.t from
stretch->buster so unrelated to these patches. However I've been giving
them a spin with the linux vdso selftests and stuff is breaking which I
guess means it's incomplete?

alex@23eb55f27ff8:~/lsrc/linux.git/tools/testing/selftests/x86$ make test_vdso
gcc -m64 -o /home/alex/lsrc/linux.git/tools/testing/selftests/x86/test_vdso_64 -O2 -g -std=gnu99 -pthread -Wall -no-pie -DCAN_BUILD_64 test_vdso.c -lrt -ldl
alex@23eb55f27ff8:~/lsrc/linux.git/tools/testing/selftests/x86$ ./test_vdso_64 
[WARN]  failed to find vDSO
[RUN]   Testing clock_gettime for clock CLOCK_REALTIME (0)...
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault (core dumped)

Also from selftests/vDSO:

alex@23eb55f27ff8:~/lsrc/linux.git/tools/testing/selftests/vDSO$ ./vdso_test 
AT_SYSINFO_EHDR is not present!

vdso_standalone_test_x86 just exits with a non-zero value. I'm still
looking into that one.

>
>
> r~
>
>
> Richard Henderson (3):
>   target/i386: Renumber EXCP_SYSCALL
>   linux-user/i386: Split out gen_signal
>   linux-user/i386: Emulate x86_64 vsyscalls
>
>  target/i386/cpu.h          |   6 +-
>  linux-user/i386/cpu_loop.c | 197 ++++++++++++++++++++++++++-----------
>  target/i386/translate.c    |  16 ++-
>  3 files changed, 155 insertions(+), 64 deletions(-)


-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls
  2020-01-14 21:09 [PATCH 0/3] linux-user: Implement x86_64 vsyscalls Richard Henderson
                   ` (6 preceding siblings ...)
  2020-01-16 14:05 ` Alex Bennée
@ 2020-01-16 14:30 ` Alex Bennée
  2020-01-16 18:31   ` Richard Henderson
  7 siblings, 1 reply; 21+ messages in thread
From: Alex Bennée @ 2020-01-16 14:30 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, pbonzini, riku.voipio, laurent, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> The x86_64 abi has a legacy vsyscall page.  The kernel folk
> have been trying to deprecate this since at least v3.1, but
>
> (1) We don't implement the vdso that replaces vsyscalls,
> (2) As of v5.5, the vsyscall page is still enabled by default.
>
> This lack is affecting Peter's linux-user testing.
>
> The dependency is not obvious because Peter is running the tests
> on x86_64, so the host is providing a vsyscall page to qemu.
>
> Because of how user-only memory operations are handled, with no
> validation of guest vs host pages, so long as qemu chooses to
> run with guest_base == 0, the guest may Just So Happen to read
> the host's vsyscall page.
>
> Complicating this, new OS releases may use a kernel configured
> with CONFIG_LEGACY_VSYSCALL_XONLY=y, which means the the vsyscall
> page cannot be read, only executed.  Which means that the guest
> then cannot read the host vsyscall page during translation and
> will SIGSEGV.
>
> Exactly which of these many variables is affecting Peter's testing
> with Ubuntu 18.04 of my TCG merge, I'm not exactly sure.  I suspect
> that it is the change to drop the textseg_addr adjustment to user-only
> static binaries.  IIRC bionic does not support -static-pie, which is
> the preferred replacement.  This could mean that the host and guest
> binaries overlap, which leads to guest_base != 0.
>
> I vaguely remember someone (Paolo?) implementing something like
> this many years ago, but clearly it never got merged.
>
> In any case, this emulation has been missing for too long.
>
>
> r~
>
>
> Richard Henderson (3):
>   target/i386: Renumber EXCP_SYSCALL
>   linux-user/i386: Split out gen_signal
>   linux-user/i386: Emulate x86_64 vsyscalls

And realising I didn't read it properly:

/x86_64-linux-user/qemu-x86_64 ~/lsrc/linux.git/tools/testing/selftests/x86/test_vsyscall_64
[WARN]  failed to find vDSO
        no vsyscall map in /proc/self/maps
[RUN]   test gettimeofday()
[RUN]   test time()
[RUN]   getcpu() on CPU 0
[RUN]   getcpu() on CPU 1
[RUN]   Checking read access to the vsyscall page
[OK]    We do not have read access: #PF(0x4)
[RUN]   Make sure that vsyscalls really page fault
**
ERROR:/home/alex/lsrc/qemu.git/linux-user/x86_64/../i386/cpu_loop.c:185:emulate_vsyscall: assertion failed: (ret != -TARGET_EFAULT)
qemu:handle_cpu_signal received signal outside vCPU context @ pc=0x7f6eed31b613

-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/3] linux-user/i386: Emulate x86_64 vsyscalls
  2020-01-14 21:09 ` [PATCH 3/3] linux-user/i386: Emulate x86_64 vsyscalls Richard Henderson
  2020-01-16 10:51   ` Alex Bennée
@ 2020-01-16 16:26   ` Alex Bennée
  2020-01-16 18:19     ` Richard Henderson
  1 sibling, 1 reply; 21+ messages in thread
From: Alex Bennée @ 2020-01-16 16:26 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, pbonzini, riku.voipio, laurent, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> 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.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/i386/cpu.h          |   1 +
>  linux-user/i386/cpu_loop.c | 104 +++++++++++++++++++++++++++++++++++++
>  target/i386/translate.c    |  16 +++++-
>  3 files changed, 120 insertions(+), 1 deletion(-)
>
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 164d038d1f..3fb2d2a986 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -1000,6 +1000,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
> diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c
> index e217cca5ee..8b7c9f7337 100644
> --- a/linux-user/i386/cpu_loop.c
> +++ b/linux-user/i386/cpu_loop.c
> @@ -92,6 +92,105 @@ static void gen_signal(CPUX86State *env, int sig, int code, abi_ptr addr)
>      queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
>  }
>  
> +#ifdef TARGET_X86_64
> +static bool write_ok_or_segv(CPUX86State *env, abi_ptr addr, size_t len)
> +{
> +    /*
> +     * For all the vsyscalls, NULL means "don't write anything" not
> +     * "write it at address 0".
> +     */
> +    if (addr == 0 || access_ok(VERIFY_WRITE, addr, len)) {
> +        return true;
> +    }
> +
> +    gen_signal(env, TARGET_SIGSEGV, TARGET_SEGV_MAPERR, addr);
> +    return false;
> +}
> +
> +/*
> + * Since v3.1, the kernel traps and emulates the vsyscall page.
> + * Entry points other than the official generate SIGSEGV.
> + */
> +static void emulate_vsyscall(CPUX86State *env)
> +{
> +    int syscall;
> +    abi_ulong ret;
> +    uint64_t caller;
> +
> +    /*
> +     * Validate the entry point.  We have already validated the page
> +     * during translation, now verify the offset.
> +     */
> +    switch (env->eip & ~TARGET_PAGE_MASK) {
> +    case 0x000:
> +        syscall = TARGET_NR_gettimeofday;
> +        break;
> +    case 0x400:
> +        syscall = TARGET_NR_time;
> +        break;
> +    case 0x800:
> +        syscall = TARGET_NR_getcpu;
> +        break;
> +    default:
> +    sigsegv:
> +        /* Like force_sig(SIGSEGV).  */
> +        gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
> +        return;
> +    }
> +
> +    /*
> +     * Validate the return address.
> +     * Note that the kernel treats this the same as an invalid entry point.
> +     */
> +    if (get_user_u64(caller, env->regs[R_ESP])) {
> +        goto sigsegv;
> +    }
> +
> +    /*
> +     * Validate the the pointer arguments.
> +     */
> +    switch (syscall) {
> +    case TARGET_NR_gettimeofday:
> +        if (!write_ok_or_segv(env, env->regs[R_EDI],
> +                              sizeof(struct target_timeval)) ||
> +            !write_ok_or_segv(env, env->regs[R_ESI],
> +                              sizeof(struct target_timezone))) {
> +            return;
> +        }
> +        break;
> +    case TARGET_NR_time:
> +        if (!write_ok_or_segv(env, env->regs[R_EDI], sizeof(abi_long))) {
> +            return;
> +        }
> +        break;
> +    case TARGET_NR_getcpu:
> +        if (!write_ok_or_segv(env, env->regs[R_EDI], sizeof(uint32_t)) ||
> +            !write_ok_or_segv(env, env->regs[R_ESI], sizeof(uint32_t))) {
> +            return;
> +        }
> +        break;
> +    default:
> +        g_assert_not_reached();
> +    }
> +
> +    /*
> +     * Perform the syscall.  None of the vsyscalls should need restarting,
> +     * and all faults should have been caught above.
> +     */
> +    ret = do_syscall(env, syscall, env->regs[R_EDI], env->regs[R_ESI],
> +                     env->regs[R_EDX], env->regs[10], env->regs[8],
> +                     env->regs[9], 0, 0);

How come the register ABI to the syscall is different to the others. I
can see why syscall doesn't come from EAX but the others are a different
set to normal syscalls which might be why:

> +    g_assert(ret != -TARGET_ERESTARTSYS);
> +    g_assert(ret != -TARGET_QEMU_ESIGRETURN);
> +    g_assert(ret != -TARGET_EFAULT);

I'm seeing a EFAULT on the gettimeofday failure:

   #0  do_syscall (cpu_env=cpu_env@entry=0x5555577d2b10, num=num@entry=96, arg1=0, arg2=0, arg3=4211016, arg4=8, arg5=274888677184, arg6=274886295415, arg7=0, arg8=0) at /home/alex/lsrc/qemu.git/linux-user/syscall.c:12076                                               
   #1  0x0000555555609b6e in emulate_vsyscall (env=0x5555577d2b10) at /home/alex/lsrc/qemu.git/linux-user/x86_64/../i386/cpu_loop.c:180
   #2  cpu_loop (env=0x5555577d2b10) at /home/alex/lsrc/qemu.git/linux-user/x86_64/../i386/cpu_loop.c:246                              
   #3  0x000055555559640e in main (argc=<optimized out>, argv=<optimized
   #out>, envp=<optimized out>) at
   #/home/alex/lsrc/qemu.git/linux-user/main.c:865

arg1/arg2 don't seem right here.

> +    env->regs[R_EAX] = ret;
> +
> +    /* Emulate a ret instruction to leave the vsyscall page.  */
> +    env->eip = caller;
> +    env->regs[R_ESP] += 8;
> +}
> +#endif
> +
>  void cpu_loop(CPUX86State *env)
>  {
>      CPUState *cs = env_cpu(env);
> @@ -141,6 +240,11 @@ void cpu_loop(CPUX86State *env)
>                  env->regs[R_EAX] = ret;
>              }
>              break;
> +#endif
> +#ifdef TARGET_X86_64
> +        case EXCP_VSYSCALL:
> +            emulate_vsyscall(env);
> +            break;
>  #endif
>          case EXCP0B_NOSEG:
>          case EXCP0C_STACK:
> diff --git a/target/i386/translate.c b/target/i386/translate.c
> index 7c99ef1385..391b4ef149 100644
> --- a/target/i386/translate.c
> +++ b/target/i386/translate.c
> @@ -8555,7 +8555,21 @@ 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;
> +
> +#if defined(TARGET_X86_64) && \
> +    defined(CONFIG_USER_ONLY) && \
> +    defined(CONFIG_LINUX)
> +    /*
> +     * Detect entry into the vsyscall page and invoke the syscall.
> +     */
> +    if ((dc->base.pc_next & TARGET_PAGE_MASK) == 0xffffffffff600000ull) {
> +        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


-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/3] linux-user/i386: Emulate x86_64 vsyscalls
  2020-01-16 16:26   ` Alex Bennée
@ 2020-01-16 18:19     ` Richard Henderson
  2020-01-16 18:22       ` Richard Henderson
  2020-01-16 20:15       ` Alex Bennée
  0 siblings, 2 replies; 21+ messages in thread
From: Richard Henderson @ 2020-01-16 18:19 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, pbonzini, riku.voipio, laurent, peter.maydell

On 1/16/20 6:26 AM, Alex Bennée wrote:
>> +    /*
>> +     * Perform the syscall.  None of the vsyscalls should need restarting,
>> +     * and all faults should have been caught above.
>> +     */
>> +    ret = do_syscall(env, syscall, env->regs[R_EDI], env->regs[R_ESI],
>> +                     env->regs[R_EDX], env->regs[10], env->regs[8],
>> +                     env->regs[9], 0, 0);
> 
> How come the register ABI to the syscall is different to the others. I
> can see why syscall doesn't come from EAX but the others are a different
> set to normal syscalls which might be why:

Cut and paste error, I assume.

That said, the three syscalls have a maximum of 2 arguments,
so I could really just pass EDI and ESI and 0 for the rest...

> I'm seeing a EFAULT on the gettimeofday failure:

What getttimeofday failure?  Is this related to the mention of /sbin/ldconfig
in your previous message?

>    #0  do_syscall (cpu_env=cpu_env@entry=0x5555577d2b10, num=num@entry=96, arg1=0, arg2=0, arg3=4211016, arg4=8, arg5=274888677184, arg6=274886295415, arg7=0, arg8=0) at /home/alex/lsrc/qemu.git/linux-user/syscall.c:12076                                               
>    #1  0x0000555555609b6e in emulate_vsyscall (env=0x5555577d2b10) at /home/alex/lsrc/qemu.git/linux-user/x86_64/../i386/cpu_loop.c:180
>    #2  cpu_loop (env=0x5555577d2b10) at /home/alex/lsrc/qemu.git/linux-user/x86_64/../i386/cpu_loop.c:246                              
>    #3  0x000055555559640e in main (argc=<optimized out>, argv=<optimized
>    #out>, envp=<optimized out>) at
>    #/home/alex/lsrc/qemu.git/linux-user/main.c:865
> 
> arg1/arg2 don't seem right here.

Why?  NULL value for arg1 is legal, though semi-useless.

Ah, I see that our implementation of gettimeofday doesn't honor NULL.


r~


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/3] linux-user/i386: Emulate x86_64 vsyscalls
  2020-01-16 18:19     ` Richard Henderson
@ 2020-01-16 18:22       ` Richard Henderson
  2020-01-16 20:15       ` Alex Bennée
  1 sibling, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2020-01-16 18:22 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, pbonzini, riku.voipio, laurent, peter.maydell

On 1/16/20 8:19 AM, Richard Henderson wrote:
> On 1/16/20 6:26 AM, Alex Bennée wrote:
>>> +    /*
>>> +     * Perform the syscall.  None of the vsyscalls should need restarting,
>>> +     * and all faults should have been caught above.
>>> +     */
>>> +    ret = do_syscall(env, syscall, env->regs[R_EDI], env->regs[R_ESI],
>>> +                     env->regs[R_EDX], env->regs[10], env->regs[8],
>>> +                     env->regs[9], 0, 0);
>>
>> How come the register ABI to the syscall is different to the others. I
>> can see why syscall doesn't come from EAX but the others are a different
>> set to normal syscalls which might be why:
> 
> Cut and paste error, I assume.

What register difference?


        case EXCP_SYSCALL:
            /* linux syscall from syscall instruction */
            ret = do_syscall(env,
                             env->regs[R_EAX],
                             env->regs[R_EDI],
                             env->regs[R_ESI],
                             env->regs[R_EDX],
                             env->regs[10],
                             env->regs[8],
                             env->regs[9],
                             0, 0);

Looks the same to me...


r~


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls
  2020-01-16 14:30 ` Alex Bennée
@ 2020-01-16 18:31   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2020-01-16 18:31 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, pbonzini, riku.voipio, laurent, peter.maydell

On 1/16/20 4:30 AM, Alex Bennée wrote:
> /x86_64-linux-user/qemu-x86_64 ~/lsrc/linux.git/tools/testing/selftests/x86/test_vsyscall_64
> [WARN]  failed to find vDSO
>         no vsyscall map in /proc/self/maps
> [RUN]   test gettimeofday()
> [RUN]   test time()
> [RUN]   getcpu() on CPU 0
> [RUN]   getcpu() on CPU 1
> [RUN]   Checking read access to the vsyscall page
> [OK]    We do not have read access: #PF(0x4)
> [RUN]   Make sure that vsyscalls really page fault
> **
> ERROR:/home/alex/lsrc/qemu.git/linux-user/x86_64/../i386/cpu_loop.c:185:emulate_vsyscall: assertion failed: (ret != -TARGET_EFAULT)
> qemu:handle_cpu_signal received signal outside vCPU context @ pc=0x7f6eed31b613

Ok, thanks.


r~



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 0/3] linux-user: Implement x86_64 vsyscalls
  2020-01-16 14:05 ` Alex Bennée
@ 2020-01-16 19:37   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2020-01-16 19:37 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, pbonzini, riku.voipio, laurent, peter.maydell

On 1/16/20 4:05 AM, Alex Bennée wrote:
> It turns out the /sbin/ldconfig crash is a regression w.r.t from
> stretch->buster so unrelated to these patches. However I've been giving
> them a spin with the linux vdso selftests and stuff is breaking which I
> guess means it's incomplete?
...
> Also from selftests/vDSO:
> 
> alex@23eb55f27ff8:~/lsrc/linux.git/tools/testing/selftests/vDSO$ ./vdso_test 
> AT_SYSINFO_EHDR is not present!

This patch set is for vsyscall only, not vdso.


r~


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/3] linux-user/i386: Emulate x86_64 vsyscalls
  2020-01-16 18:19     ` Richard Henderson
  2020-01-16 18:22       ` Richard Henderson
@ 2020-01-16 20:15       ` Alex Bennée
  1 sibling, 0 replies; 21+ messages in thread
From: Alex Bennée @ 2020-01-16 20:15 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, pbonzini, riku.voipio, laurent, peter.maydell


Richard Henderson <richard.henderson@linaro.org> writes:

> On 1/16/20 6:26 AM, Alex Bennée wrote:
>>> +    /*
>>> +     * Perform the syscall.  None of the vsyscalls should need restarting,
>>> +     * and all faults should have been caught above.
>>> +     */
>>> +    ret = do_syscall(env, syscall, env->regs[R_EDI], env->regs[R_ESI],
>>> +                     env->regs[R_EDX], env->regs[10], env->regs[8],
>>> +                     env->regs[9], 0, 0);
>> 
>> How come the register ABI to the syscall is different to the others. I
>> can see why syscall doesn't come from EAX but the others are a different
>> set to normal syscalls which might be why:
>
> Cut and paste error, I assume.
>
> That said, the three syscalls have a maximum of 2 arguments,
> so I could really just pass EDI and ESI and 0 for the rest...
>
>> I'm seeing a EFAULT on the gettimeofday failure:
>
> What getttimeofday failure?  Is this related to the mention of /sbin/ldconfig
> in your previous message?

No - the buster x86064 ldconfig seg is unrelated to this series. It has
however spawned an additional bug in gdbstub while it was at it ;-)

>
>>    #0  do_syscall (cpu_env=cpu_env@entry=0x5555577d2b10, num=num@entry=96, arg1=0, arg2=0, arg3=4211016, arg4=8, arg5=274888677184, arg6=274886295415, arg7=0, arg8=0) at /home/alex/lsrc/qemu.git/linux-user/syscall.c:12076                                               
>>    #1  0x0000555555609b6e in emulate_vsyscall (env=0x5555577d2b10) at /home/alex/lsrc/qemu.git/linux-user/x86_64/../i386/cpu_loop.c:180
>>    #2  cpu_loop (env=0x5555577d2b10) at /home/alex/lsrc/qemu.git/linux-user/x86_64/../i386/cpu_loop.c:246                              
>>    #3  0x000055555559640e in main (argc=<optimized out>, argv=<optimized
>>    #out>, envp=<optimized out>) at
>>    #/home/alex/lsrc/qemu.git/linux-user/main.c:865
>> 
>> arg1/arg2 don't seem right here.
>
> Why?  NULL value for arg1 is legal, though semi-useless.
>
> Ah, I see that our implementation of gettimeofday doesn't honor NULL.
>
>
> r~


-- 
Alex Bennée


^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, back to index

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-14 21:09 [PATCH 0/3] linux-user: Implement x86_64 vsyscalls Richard Henderson
2020-01-14 21:09 ` [PATCH 1/3] target/i386: Renumber EXCP_SYSCALL Richard Henderson
2020-01-15  7:22   ` Philippe Mathieu-Daudé
2020-01-15  9:55   ` Alex Bennée
2020-01-14 21:09 ` [PATCH 2/3] linux-user/i386: Split out gen_signal Richard Henderson
2020-01-15  7:22   ` Philippe Mathieu-Daudé
2020-01-15  9:58   ` Alex Bennée
2020-01-14 21:09 ` [PATCH 3/3] linux-user/i386: Emulate x86_64 vsyscalls Richard Henderson
2020-01-16 10:51   ` Alex Bennée
2020-01-16 16:26   ` Alex Bennée
2020-01-16 18:19     ` Richard Henderson
2020-01-16 18:22       ` Richard Henderson
2020-01-16 20:15       ` Alex Bennée
2020-01-14 23:35 ` [PATCH 0/3] linux-user: Implement " Paolo Bonzini
2020-01-15  7:01 ` Laurent Desnogues
2020-01-15 10:14 ` Laurent Vivier
2020-01-15 17:28   ` Richard Henderson
2020-01-16 14:05 ` Alex Bennée
2020-01-16 19:37   ` Richard Henderson
2020-01-16 14:30 ` Alex Bennée
2020-01-16 18:31   ` Richard Henderson

QEMU-Devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/qemu-devel/0 qemu-devel/git/0.git
	git clone --mirror https://lore.kernel.org/qemu-devel/1 qemu-devel/git/1.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 qemu-devel qemu-devel/ https://lore.kernel.org/qemu-devel \
		qemu-devel@nongnu.org
	public-inbox-index qemu-devel

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.nongnu.qemu-devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git