Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp1689094ybi; Wed, 17 Jul 2019 20:10:16 -0700 (PDT) X-Google-Smtp-Source: APXvYqwmfuwmpZVXr8kREXSxDOZaJLR2RssWcAKnbuBz6ys7TUJFml7Gsx9Vkx7+Y7KXUKXGe0z7 X-Received: by 2002:a17:902:aa95:: with SMTP id d21mr45456328plr.185.1563419416306; Wed, 17 Jul 2019 20:10:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1563419416; cv=none; d=google.com; s=arc-20160816; b=x9dOQvBeb22sQujdasS+1kq07gD57frA3fJVPweXTOEYMl8mHk+5lAtsT8lRiwf1wN eG+mzlN2veV+bgx34qIE1gAlIoJ5YI4KL4oLrn8dWfmNUUqG4AqzuH75VMeqqpxUSd2a xE49MgDF6VFm9tJryj5XFw8cT5sW1iav/86p9RQoKrtIAJww95A43eehQIqt1hIuct/N Pkm83T7zJfOtNEH6CJyxMbUgANoqIVOpMVCqtDXes66V4vO8zn8Ynz8ahMC0rR0u7r7u FNNWkm2175rNZxjMzSkauTEl+CnFwqH0Hnb2o+M8C1zQaUujrI/mqnlPuwVsY7RfkkqU EyjA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=4YLN0JzymfVTH+UK6xwUgtc/EkxOWTg52QsFgGWwVtk=; b=qN6NPaFXr7hRpd+6KfEnWTdEheGJEfatB2hxT/sFCvuYsnLPF8ekeyqLBlwPhGWqPD SCtW2m/J46mBT+m0fPAknCF08fgAa7akNNBox5iKeB/8cvGI5+WsfnWeb9LB+NtYz0gG fDyGuKw1rQRRiBin1dj7QFp5kY2MFz0fEj+ExgJiMM4D+0ds2PeiQN9zOcsmxrmGhJxu Qqb9Q53qb3H7/dPBVCgTnlEXPD1IsDl/YfdqUUCQagtJpECPm9ajE3ZR+apZmCbKSg85 XChB5Phsh9rIfaezK7qVmqckKEyPdBt1VVm7f4gu7HX92oDvN22Fo6ZDMcmh76Qb4S8d Vr0A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=lo7s+pPI; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j74si714520pje.12.2019.07.17.20.10.00; Wed, 17 Jul 2019 20:10:16 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=lo7s+pPI; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2390503AbfGRDHi (ORCPT + 99 others); Wed, 17 Jul 2019 23:07:38 -0400 Received: from mail.kernel.org ([198.145.29.99]:39280 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389728AbfGRDHg (ORCPT ); Wed, 17 Jul 2019 23:07:36 -0400 Received: from localhost (115.42.148.210.bf.2iij.net [210.148.42.115]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 6922F21848; Thu, 18 Jul 2019 03:07:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1563419254; bh=Ll0mToFWxutfEGmwbbvOvd2laMWvkUQ53iF9q3c6kns=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lo7s+pPIBYHKHsn+FgTXO8tI1RnQho2HrZGxUsOzdZcnmuIE+9gQ34U+Mz0jvs6c1 BgQr4va27MIa6xMvuo8yrcv51U2nq9l6Yq7xiBBKA221Cj0zoVqPfydmInghnJp4yW 9qRxZzuZdfv1+9qOwf80FYVr3NdjAznqPRM6X3J8= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Thomas Gleixner , Jason Cooper , Heyi Guo , Marc Zyngier , Sasha Levin Subject: [PATCH 4.19 07/47] irqchip/gic-v3-its: Fix command queue pointer comparison bug Date: Thu, 18 Jul 2019 12:01:21 +0900 Message-Id: <20190718030049.020637230@linuxfoundation.org> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20190718030045.780672747@linuxfoundation.org> References: <20190718030045.780672747@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org [ Upstream commit a050fa5476d418fc16b25abe168b3d38ba11e13c ] When we run several VMs with PCI passthrough and GICv4 enabled, not pinning vCPUs, we will occasionally see below warnings in dmesg: ITS queue timeout (65440 65504 480) ITS cmd its_build_vmovp_cmd failed The reason for the above issue is that in BUILD_SINGLE_CMD_FUNC: 1. Post the write command. 2. Release the lock. 3. Start to read GITS_CREADR to get the reader pointer. 4. Compare the reader pointer to the target pointer. 5. If reader pointer does not reach the target, sleep 1us and continue to try. If we have several processors running the above concurrently, other CPUs will post write commands while the 1st CPU is waiting the completion. So we may have below issue: phase 1: ---rd_idx-----from_idx-----to_idx--0--------- wait 1us: phase 2: --------------from_idx-----to_idx--0-rd_idx-- That is the rd_idx may fly ahead of to_idx, and if in case to_idx is near the wrap point, rd_idx will wrap around. So the below condition will not be met even after 1s: if (from_idx < to_idx && rd_idx >= to_idx) There is another theoretical issue. For a slow and busy ITS, the initial rd_idx may fall behind from_idx a lot, just as below: ---rd_idx---0--from_idx-----to_idx----------- This will cause the wait function exit too early. Actually, it does not make much sense to use from_idx to judge if to_idx is wrapped, but we need a initial rd_idx when lock is still acquired, and it can be used to judge whether to_idx is wrapped and the current rd_idx is wrapped. We switch to a method of calculating the delta of two adjacent reads and accumulating it to get the sum, so that we can get the real rd_idx from the wrapped value even when the queue is almost full. Cc: Thomas Gleixner Cc: Jason Cooper Signed-off-by: Heyi Guo Signed-off-by: Marc Zyngier Signed-off-by: Sasha Levin --- drivers/irqchip/irq-gic-v3-its.c | 35 ++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 65ab2c80529c..ee30e8965d1b 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -740,32 +740,43 @@ static void its_flush_cmd(struct its_node *its, struct its_cmd_block *cmd) } static int its_wait_for_range_completion(struct its_node *its, - struct its_cmd_block *from, + u64 prev_idx, struct its_cmd_block *to) { - u64 rd_idx, from_idx, to_idx; + u64 rd_idx, to_idx, linear_idx; u32 count = 1000000; /* 1s! */ - from_idx = its_cmd_ptr_to_offset(its, from); + /* Linearize to_idx if the command set has wrapped around */ to_idx = its_cmd_ptr_to_offset(its, to); + if (to_idx < prev_idx) + to_idx += ITS_CMD_QUEUE_SZ; + + linear_idx = prev_idx; while (1) { + s64 delta; + rd_idx = readl_relaxed(its->base + GITS_CREADR); - /* Direct case */ - if (from_idx < to_idx && rd_idx >= to_idx) - break; + /* + * Compute the read pointer progress, taking the + * potential wrap-around into account. + */ + delta = rd_idx - prev_idx; + if (rd_idx < prev_idx) + delta += ITS_CMD_QUEUE_SZ; - /* Wrapped case */ - if (from_idx >= to_idx && rd_idx >= to_idx && rd_idx < from_idx) + linear_idx += delta; + if (linear_idx >= to_idx) break; count--; if (!count) { - pr_err_ratelimited("ITS queue timeout (%llu %llu %llu)\n", - from_idx, to_idx, rd_idx); + pr_err_ratelimited("ITS queue timeout (%llu %llu)\n", + to_idx, linear_idx); return -1; } + prev_idx = rd_idx; cpu_relax(); udelay(1); } @@ -782,6 +793,7 @@ void name(struct its_node *its, \ struct its_cmd_block *cmd, *sync_cmd, *next_cmd; \ synctype *sync_obj; \ unsigned long flags; \ + u64 rd_idx; \ \ raw_spin_lock_irqsave(&its->lock, flags); \ \ @@ -803,10 +815,11 @@ void name(struct its_node *its, \ } \ \ post: \ + rd_idx = readl_relaxed(its->base + GITS_CREADR); \ next_cmd = its_post_commands(its); \ raw_spin_unlock_irqrestore(&its->lock, flags); \ \ - if (its_wait_for_range_completion(its, cmd, next_cmd)) \ + if (its_wait_for_range_completion(its, rd_idx, next_cmd)) \ pr_err_ratelimited("ITS cmd %ps failed\n", builder); \ } -- 2.20.1