stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Heyi Guo <guoheyi@huawei.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Jason Cooper <jason@lakedaemon.net>,
	Marc Zyngier <marc.zyngier@arm.com>,
	Sasha Levin <sashal@kernel.org>
Subject: [PATCH AUTOSEL 5.1 05/39] irqchip/gic-v3-its: Fix command queue pointer comparison bug
Date: Tue,  2 Jul 2019 22:14:40 -0400	[thread overview]
Message-ID: <20190703021514.17727-5-sashal@kernel.org> (raw)
In-Reply-To: <20190703021514.17727-1-sashal@kernel.org>

From: Heyi Guo <guoheyi@huawei.com>

[ 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 <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Signed-off-by: Heyi Guo <guoheyi@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 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 7577755bdcf4..eead9def9921 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -745,32 +745,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);
 	}
@@ -787,6 +798,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);			\
 									\
@@ -808,10 +820,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


  parent reply	other threads:[~2019-07-03  2:15 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-03  2:14 [PATCH AUTOSEL 5.1 01/39] ARM: dts: meson8: fix GPU interrupts and drop an undocumented property Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 02/39] ARM: dts: meson8b: fix the operating voltage of the Mali GPU Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 03/39] idr: Fix idr_get_next race with idr_remove Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 04/39] irqchip/irq-csky-mpintc: Support auto irq deliver to all cpus Sasha Levin
2019-07-03  2:14 ` Sasha Levin [this message]
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 06/39] clk: ti: clkctrl: Fix returning uninitialized data Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 07/39] efi/bgrt: Drop BGRT status field reserved bits check Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 08/39] arm64: dts: ls1028a: Fix CPU idle fail Sasha Levin
2019-07-11  5:04   ` Ran Wang
2019-07-11  6:43     ` Greg KH
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 09/39] selftests/powerpc: Add test of fork with mapping above 512TB Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 10/39] perf/core: Fix perf_sample_regs_user() mm check Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 11/39] ARM: dts: gemini Fix up DNS-313 compatible string Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 12/39] ARM: omap2: remove incorrect __init annotation Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 13/39] afs: Fix uninitialised spinlock afs_volume::cb_break_lock Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 14/39] x86/efi: fix a -Wtype-limits compilation warning Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 15/39] x86/apic: Fix integer overflow on 10 bit left shift of cpu_khz Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 16/39] be2net: fix link failure after ethtool offline test Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 17/39] ppp: mppe: Add softdep to arc4 Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 18/39] net: stmmac: fixed new system time seconds value calculation Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 19/39] net: stmmac: set IC bit when transmitting frames with HW timestamp Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 20/39] sis900: fix TX completion Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 21/39] ARM: dts: imx6ul: fix PWM[1-4] interrupts Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 22/39] qmi_wwan: Fix out-of-bounds read Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 23/39] pinctrl: mcp23s08: Fix add_data and irqchip_add_nested call order Sasha Levin
2019-07-03  2:14 ` [PATCH AUTOSEL 5.1 24/39] pinctrl: ocelot: fix gpio direction for pins after 31 Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 25/39] pinctrl: ocelot: fix pinmuxing " Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 26/39] dm table: don't copy from a NULL pointer in realloc_argv() Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 27/39] dm verity: use message limit for data block corruption message Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 28/39] x86/boot/64: Fix crash if kernel image crosses page table boundary Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 29/39] x86/boot/64: Add missing fixup_pointer() for next_early_pgt access Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 30/39] HID: chicony: add another quirk for PixArt mouse Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 31/39] HID: uclogic: Add support for Huion HS64 tablet Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 32/39] HID: multitouch: Add pointstick support for ALPS Touchpad Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 33/39] pinctrl: mediatek: Ignore interrupts that are wake only during resume Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 34/39] net: aquantia: fix vlans not working over bridged network Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 35/39] cpu/hotplug: Fix out-of-bounds read when setting fail state Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 36/39] pinctrl: mediatek: Update cur_mask in mask/mask ops Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 37/39] mm/oom_kill.c: fix uninitialized oc->constraint Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 38/39] fork,memcg: alloc_thread_stack_node needs to set tsk->stack Sasha Levin
2019-07-03  2:15 ` [PATCH AUTOSEL 5.1 39/39] linux/kernel.h: fix overflow for DIV_ROUND_UP_ULL Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190703021514.17727-5-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=guoheyi@huawei.com \
    --cc=jason@lakedaemon.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marc.zyngier@arm.com \
    --cc=stable@vger.kernel.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).