From nobody Thu Nov 6 19:45:24 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1488216785026741.9071613423858; Mon, 27 Feb 2017 09:33:05 -0800 (PST) Received: from localhost ([::1]:54987 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPAV-0007TH-Ge for importer@patchew.org; Mon, 27 Feb 2017 12:33:03 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51363) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciOUl-0004DC-J0 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 11:49:57 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciOUk-0006Wu-6d for qemu-devel@nongnu.org; Mon, 27 Feb 2017 11:49:55 -0500 Received: from mx1.redhat.com ([209.132.183.28]:48020) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciOUj-0006Wm-Tr for qemu-devel@nongnu.org; Mon, 27 Feb 2017 11:49:54 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 09B0D4E4D2 for ; Mon, 27 Feb 2017 16:49:54 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-118.ams2.redhat.com [10.36.117.118]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1RGno4U030602 for ; Mon, 27 Feb 2017 11:49:53 -0500 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 17:49:50 +0100 Message-Id: <20170227164950.15062-3-pbonzini@redhat.com> In-Reply-To: <20170227164950.15062-1-pbonzini@redhat.com> References: <20170227164950.15062-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Mon, 27 Feb 2017 16:49:54 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 10/17] KVM: do not use sigtimedwait to catch SIGBUS X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Call kvm_on_sigbus_vcpu asynchronously from the VCPU thread. Information for the SIGBUS can be stored in thread-local variables and processed later in kvm_cpu_exec. Signed-off-by: Paolo Bonzini --- cpus.c | 31 +++++++++++++------------------ include/sysemu/kvm.h | 5 ++++- kvm-all.c | 37 ++++++++++++++++++++++++++++++++++++- target/arm/kvm.c | 5 ----- target/i386/kvm.c | 5 ++--- target/mips/kvm.c | 6 ------ target/ppc/kvm.c | 5 ----- target/s390x/kvm.c | 5 ----- 8 files changed, 55 insertions(+), 44 deletions(-) diff --git a/cpus.c b/cpus.c index 399e271..56b1338 100644 --- a/cpus.c +++ b/cpus.c @@ -926,8 +926,16 @@ static void sigbus_handler(int n, siginfo_t *siginfo, = void *ctx) sigbus_reraise(); } =20 - if (kvm_on_sigbus(siginfo->si_code, siginfo->si_addr)) { - sigbus_reraise(); + if (current_cpu) { + /* Called asynchronously in VCPU thread. */ + if (kvm_on_sigbus_vcpu(current_cpu, siginfo->si_code, siginfo->si_= addr)) { + sigbus_reraise(); + } + } else { + /* Called synchronously (via signalfd) in main thread. */ + if (kvm_on_sigbus(siginfo->si_code, siginfo->si_addr)) { + sigbus_reraise(); + } } } =20 @@ -958,8 +966,9 @@ static void qemu_kvm_init_cpu_signals(CPUState *cpu) sigaction(SIG_IPI, &sigact, NULL); =20 pthread_sigmask(SIG_BLOCK, NULL, &set); - sigdelset(&set, SIG_IPI); sigdelset(&set, SIGBUS); + pthread_sigmask(SIG_SETMASK, &set, NULL); + sigdelset(&set, SIG_IPI); r =3D kvm_set_signal_mask(cpu, &set); if (r) { fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r)); @@ -977,7 +986,6 @@ static void qemu_kvm_eat_signals(CPUState *cpu) =20 sigemptyset(&waitset); sigaddset(&waitset, SIG_IPI); - sigaddset(&waitset, SIGBUS); =20 do { r =3D sigtimedwait(&waitset, &siginfo, &ts); @@ -986,25 +994,12 @@ static void qemu_kvm_eat_signals(CPUState *cpu) exit(1); } =20 - switch (r) { - case SIGBUS: - if (siginfo.si_code !=3D BUS_MCEERR_AO && siginfo.si_code !=3D= BUS_MCEERR_AR) { - sigbus_reraise(); - } - if (kvm_on_sigbus_vcpu(cpu, siginfo.si_code, siginfo.si_addr))= { - sigbus_reraise(); - } - break; - default: - break; - } - r =3D sigpending(&chkset); if (r =3D=3D -1) { perror("sigpending"); exit(1); } - } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS)= ); + } while (sigismember(&chkset, SIG_IPI)); } #else /* !CONFIG_LINUX */ static void qemu_init_sigbus(void) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 6ecb61c..a1b019d 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -357,7 +357,10 @@ bool kvm_vcpu_id_is_valid(int vcpu_id); /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */ unsigned long kvm_arch_vcpu_id(CPUState *cpu); =20 -int kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr); +#ifdef TARGET_I386 +#define KVM_HAVE_MCE_INJECTION 1 +void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr); +#endif =20 void kvm_arch_init_irq_routing(KVMState *s); =20 diff --git a/kvm-all.c b/kvm-all.c index a433ad3..9e7c09f 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1893,6 +1893,12 @@ void kvm_cpu_synchronize_post_init(CPUState *cpu) run_on_cpu(cpu, do_kvm_cpu_synchronize_post_init, RUN_ON_CPU_NULL); } =20 +#ifdef KVM_HAVE_MCE_INJECTION +static __thread void *pending_sigbus_addr; +static __thread int pending_sigbus_code; +static __thread bool have_sigbus_pending; +#endif + int kvm_cpu_exec(CPUState *cpu) { struct kvm_run *run =3D cpu->kvm_run; @@ -1930,6 +1936,18 @@ int kvm_cpu_exec(CPUState *cpu) =20 attrs =3D kvm_arch_post_run(cpu, run); =20 + if (unlikely(have_sigbus_pending)) { +#ifdef KVM_HAVE_MCE_INJECTION + qemu_mutex_lock_iothread(); + kvm_arch_on_sigbus_vcpu(cpu, pending_sigbus_code, + pending_sigbus_addr); + have_sigbus_pending =3D false; + qemu_mutex_unlock_iothread(); +#else + abort(); +#endif + } + if (run_ret < 0) { if (run_ret =3D=3D -EINTR || run_ret =3D=3D -EAGAIN) { DPRINTF("io window exit\n"); @@ -2392,13 +2410,27 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset= _t *sigset) return r; } =20 +/* Called asynchronously in VCPU thread. */ int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr) { - return kvm_arch_on_sigbus_vcpu(cpu, code, addr); +#ifdef KVM_HAVE_MCE_INJECTION + if (have_sigbus_pending) { + return 1; + } + have_sigbus_pending =3D true; + pending_sigbus_addr =3D addr; + pending_sigbus_code =3D code; + atomic_set(&cpu->exit_request, 1); + return 0; +#else + return 1; +#endif } =20 +/* Called synchronously (via signalfd) in main thread. */ int kvm_on_sigbus(int code, void *addr) { +#ifdef KVM_HAVE_MCE_INJECTION /* Action required MCE kills the process if SIGBUS is blocked. Because * that's what happens in the I/O thread, where we handle MCE via sign= alfd, * we can only get action optional here. @@ -2406,6 +2438,9 @@ int kvm_on_sigbus(int code, void *addr) assert(code !=3D BUS_MCEERR_AR); kvm_arch_on_sigbus_vcpu(first_cpu, code, addr); return 0; +#else + return 1; +#endif } =20 int kvm_create_device(KVMState *s, uint64_t type, bool test) diff --git a/target/arm/kvm.c b/target/arm/kvm.c index e5218f6..4555468 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -560,11 +560,6 @@ int kvm_arch_process_async_events(CPUState *cs) return 0; } =20 -int kvm_arch_on_sigbus_vcpu(CPUState *cs, int code, void *addr) -{ - return 1; -} - /* The #ifdef protections are until 32bit headers are imported and can * be removed once both 32 and 64 bit reach feature parity. */ diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 2adf992..7698421 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -455,7 +455,7 @@ static void hardware_memory_error(void) exit(1); } =20 -int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) { X86CPU *cpu =3D X86_CPU(c); CPUX86State *env =3D &cpu->env; @@ -475,7 +475,7 @@ int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void= *addr) kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)= ) { kvm_hwpoison_page_add(ram_addr); kvm_mce_inject(cpu, paddr, code); - return 0; + return; } =20 fprintf(stderr, "Hardware memory error for memory used by " @@ -487,7 +487,6 @@ int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void= *addr) } =20 /* Hope we are lucky for AO MCE */ - return 0; } =20 static int kvm_inject_mce_oldstyle(X86CPU *cpu) diff --git a/target/mips/kvm.c b/target/mips/kvm.c index 3e686e7..0982e87 100644 --- a/target/mips/kvm.c +++ b/target/mips/kvm.c @@ -180,12 +180,6 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cs) return true; } =20 -int kvm_arch_on_sigbus_vcpu(CPUState *cs, int code, void *addr) -{ - DPRINTF("%s\n", __func__); - return 1; -} - void kvm_arch_init_irq_routing(KVMState *s) { } diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index bc011c6..f22ecab 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -2582,11 +2582,6 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cpu) return true; } =20 -int kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr) -{ - return 1; -} - void kvm_arch_init_irq_routing(KVMState *s) { } diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index e7eea6d..ac47154 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -2140,11 +2140,6 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cpu) return true; } =20 -int kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr) -{ - return 1; -} - void kvm_s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, uint32_t io_int_parm, uint32_t io_int_word) --=20 2.9.3