From nobody Mon May 6 00:49:42 2024 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.zohomail.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; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543227015147927.5085547914476; Mon, 26 Nov 2018 02:10:15 -0800 (PST) Received: from localhost ([::1]:34964 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gRDqC-0005Xc-UE for importer@patchew.org; Mon, 26 Nov 2018 05:10:08 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53597) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gRDot-0004ty-RK for qemu-devel@nongnu.org; Mon, 26 Nov 2018 05:08:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gRDon-0004hf-JM for qemu-devel@nongnu.org; Mon, 26 Nov 2018 05:08:47 -0500 Received: from mx1.redhat.com ([209.132.183.28]:34012) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gRDon-0004gy-Dw for qemu-devel@nongnu.org; Mon, 26 Nov 2018 05:08:41 -0500 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B874C307CEBD for ; Mon, 26 Nov 2018 10:08:40 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-59.ams2.redhat.com [10.36.116.59]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8D34F261A6; Mon, 26 Nov 2018 10:08:37 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id CEC695DEFD; Mon, 26 Nov 2018 11:08:36 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Mon, 26 Nov 2018 11:08:36 +0100 Message-Id: <20181126100836.8805-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.44]); Mon, 26 Nov 2018 10:08:40 +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] [PATCH] ehci: fix fetch qtd race 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: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The token field contains the (guest-filled) state of the qtd, which indicates whenever the other fields are valid or not. So make sure we read the token first, otherwise we may end up with an stale next pointer: (1) ehci reads next (2) guest writes next (3) guest writes token (4) ehci reads token (5) ehci operates with stale next. Typical effect is that qemu doesn't notice that the guest appends new qtds to the end of the queue. Looks like the usb device stopped responding. Linux can recover from that, but leaves a message in the kernel log that it did reset the usb device in question. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index e5acfc5ba5..8d44d483df 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1783,9 +1783,17 @@ static int ehci_state_fetchqtd(EHCIQueue *q) EHCIqtd qtd; EHCIPacket *p; int again =3D 1; + uint32_t addr; =20 - if (get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &qtd, - sizeof(EHCIqtd) >> 2) < 0) { + addr =3D NLPTR_GET(q->qtdaddr); + if (get_dwords(q->ehci, addr + 8, &qtd.token, 1) < 0) { + return 0; + } + barrier(); + if (get_dwords(q->ehci, addr + 0, &qtd.next, 1) < 0 || + get_dwords(q->ehci, addr + 4, &qtd.altnext, 1) < 0 || + get_dwords(q->ehci, addr + 12, qtd.bufptr, + ARRAY_SIZE(qtd.bufptr)) < 0) { return 0; } ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd); --=20 2.9.3