linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH AUTOSEL 4.19 01/26] irqchip/gic-v3-its: Fix command queue pointer comparison bug
@ 2019-07-03  2:16 Sasha Levin
  2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 02/26] clk: ti: clkctrl: Fix returning uninitialized data Sasha Levin
                   ` (24 more replies)
  0 siblings, 25 replies; 26+ messages in thread
From: Sasha Levin @ 2019-07-03  2:16 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Heyi Guo, Thomas Gleixner, Jason Cooper, Marc Zyngier, Sasha Levin

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 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


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

end of thread, other threads:[~2019-07-03  2:21 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-03  2:16 [PATCH AUTOSEL 4.19 01/26] irqchip/gic-v3-its: Fix command queue pointer comparison bug Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 02/26] clk: ti: clkctrl: Fix returning uninitialized data Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 03/26] efi/bgrt: Drop BGRT status field reserved bits check Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 04/26] perf/core: Fix perf_sample_regs_user() mm check Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 05/26] ARM: dts: gemini Fix up DNS-313 compatible string Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 06/26] ARM: omap2: remove incorrect __init annotation Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 07/26] afs: Fix uninitialised spinlock afs_volume::cb_break_lock Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 08/26] x86/apic: Fix integer overflow on 10 bit left shift of cpu_khz Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 09/26] be2net: fix link failure after ethtool offline test Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 10/26] ppp: mppe: Add softdep to arc4 Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 11/26] net: stmmac: fixed new system time seconds value calculation Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 12/26] net: stmmac: set IC bit when transmitting frames with HW timestamp Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 13/26] sis900: fix TX completion Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 14/26] ARM: dts: imx6ul: fix PWM[1-4] interrupts Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 15/26] qmi_wwan: Fix out-of-bounds read Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 16/26] pinctrl: mcp23s08: Fix add_data and irqchip_add_nested call order Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 17/26] dm table: don't copy from a NULL pointer in realloc_argv() Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 18/26] dm verity: use message limit for data block corruption message Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 19/26] x86/boot/64: Fix crash if kernel image crosses page table boundary Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 20/26] x86/boot/64: Add missing fixup_pointer() for next_early_pgt access Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 21/26] HID: chicony: add another quirk for PixArt mouse Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 22/26] HID: multitouch: Add pointstick support for ALPS Touchpad Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 23/26] pinctrl: mediatek: Ignore interrupts that are wake only during resume Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 24/26] cpu/hotplug: Fix out-of-bounds read when setting fail state Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 25/26] pinctrl: mediatek: Update cur_mask in mask/mask ops Sasha Levin
2019-07-03  2:16 ` [PATCH AUTOSEL 4.19 26/26] linux/kernel.h: fix overflow for DIV_ROUND_UP_ULL Sasha Levin

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).