From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: "Guilherme G. Piccoli" <gpiccoli@igalia.com>,
Andrea Parri <parri.andrea@gmail.com>,
Dexuan Cui <decui@microsoft.com>,
Haiyang Zhang <haiyangz@microsoft.com>,
"K. Y. Srinivasan" <kys@microsoft.com>,
Michael Kelley <mikelley@microsoft.com>,
Stephen Hemminger <sthemmin@microsoft.com>,
Tianyu Lan <Tianyu.Lan@microsoft.com>,
Wei Liu <wei.liu@kernel.org>,
Fabio A M Martins <fabiomirmar@gmail.com>,
Sasha Levin <sashal@kernel.org>,
deller@gmx.de, linux-hyperv@vger.kernel.org,
linux-fbdev@vger.kernel.org, dri-devel@lists.freedesktop.org
Subject: [PATCH AUTOSEL 5.15 3/5] video: hyperv_fb: Avoid taking busy spinlock on panic path
Date: Fri, 16 Dec 2022 19:10:36 -0500 [thread overview]
Message-ID: <20221217001038.41355-3-sashal@kernel.org> (raw)
In-Reply-To: <20221217001038.41355-1-sashal@kernel.org>
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com>
[ Upstream commit 1d044ca035dc22df0d3b39e56f2881071d9118bd ]
The Hyper-V framebuffer code registers a panic notifier in order
to try updating its fbdev if the kernel crashed. The notifier
callback is straightforward, but it calls the vmbus_sendpacket()
routine eventually, and such function takes a spinlock for the
ring buffer operations.
Panic path runs in atomic context, with local interrupts and
preemption disabled, and all secondary CPUs shutdown. That said,
taking a spinlock might cause a lockup if a secondary CPU was
disabled with such lock taken. Fix it here by checking if the
ring buffer spinlock is busy on Hyper-V framebuffer panic notifier;
if so, bail-out avoiding the potential lockup scenario.
Cc: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Cc: Dexuan Cui <decui@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Michael Kelley <mikelley@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: Tianyu Lan <Tianyu.Lan@microsoft.com>
Cc: Wei Liu <wei.liu@kernel.org>
Tested-by: Fabio A M Martins <fabiomirmar@gmail.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Link: https://lore.kernel.org/r/20220819221731.480795-10-gpiccoli@igalia.com
Signed-off-by: Wei Liu <wei.liu@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/hv/ring_buffer.c | 13 +++++++++++++
drivers/video/fbdev/hyperv_fb.c | 8 +++++++-
include/linux/hyperv.h | 2 ++
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index f4091143213b..1475ea77351e 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -249,6 +249,19 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info)
ring_info->pkt_buffer_size = 0;
}
+/*
+ * Check if the ring buffer spinlock is available to take or not; used on
+ * atomic contexts, like panic path (see the Hyper-V framebuffer driver).
+ */
+
+bool hv_ringbuffer_spinlock_busy(struct vmbus_channel *channel)
+{
+ struct hv_ring_buffer_info *rinfo = &channel->outbound;
+
+ return spin_is_locked(&rinfo->ring_lock);
+}
+EXPORT_SYMBOL_GPL(hv_ringbuffer_spinlock_busy);
+
/* Write to the ring buffer. */
int hv_ringbuffer_write(struct vmbus_channel *channel,
const struct kvec *kv_list, u32 kv_count,
diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c
index 58c304a3b7c4..de865e197c8d 100644
--- a/drivers/video/fbdev/hyperv_fb.c
+++ b/drivers/video/fbdev/hyperv_fb.c
@@ -799,12 +799,18 @@ static void hvfb_ondemand_refresh_throttle(struct hvfb_par *par,
static int hvfb_on_panic(struct notifier_block *nb,
unsigned long e, void *p)
{
+ struct hv_device *hdev;
struct hvfb_par *par;
struct fb_info *info;
par = container_of(nb, struct hvfb_par, hvfb_panic_nb);
- par->synchronous_fb = true;
info = par->info;
+ hdev = device_to_hv_device(info->device);
+
+ if (hv_ringbuffer_spinlock_busy(hdev->channel))
+ return NOTIFY_DONE;
+
+ par->synchronous_fb = true;
if (par->need_docopy)
hvfb_docopy(par, 0, dio_fb_size);
synthvid_update(info, 0, 0, INT_MAX, INT_MAX);
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index ddc8713ce57b..8499fc9220e0 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1307,6 +1307,8 @@ struct hv_ring_buffer_debug_info {
int hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
struct hv_ring_buffer_debug_info *debug_info);
+bool hv_ringbuffer_spinlock_busy(struct vmbus_channel *channel);
+
/* Vmbus interface */
#define vmbus_driver_register(driver) \
__vmbus_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
--
2.35.1
WARNING: multiple messages have this Message-ID (diff)
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Andrea Parri <parri.andrea@gmail.com>,
Sasha Levin <sashal@kernel.org>, Wei Liu <wei.liu@kernel.org>,
Stephen Hemminger <sthemmin@microsoft.com>,
Fabio A M Martins <fabiomirmar@gmail.com>,
Haiyang Zhang <haiyangz@microsoft.com>,
Dexuan Cui <decui@microsoft.com>,
linux-hyperv@vger.kernel.org, dri-devel@lists.freedesktop.org,
Michael Kelley <mikelley@microsoft.com>,
"Guilherme G. Piccoli" <gpiccoli@igalia.com>,
linux-fbdev@vger.kernel.org,
Tianyu Lan <Tianyu.Lan@microsoft.com>,
"K. Y. Srinivasan" <kys@microsoft.com>,
deller@gmx.de
Subject: [PATCH AUTOSEL 5.15 3/5] video: hyperv_fb: Avoid taking busy spinlock on panic path
Date: Fri, 16 Dec 2022 19:10:36 -0500 [thread overview]
Message-ID: <20221217001038.41355-3-sashal@kernel.org> (raw)
In-Reply-To: <20221217001038.41355-1-sashal@kernel.org>
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com>
[ Upstream commit 1d044ca035dc22df0d3b39e56f2881071d9118bd ]
The Hyper-V framebuffer code registers a panic notifier in order
to try updating its fbdev if the kernel crashed. The notifier
callback is straightforward, but it calls the vmbus_sendpacket()
routine eventually, and such function takes a spinlock for the
ring buffer operations.
Panic path runs in atomic context, with local interrupts and
preemption disabled, and all secondary CPUs shutdown. That said,
taking a spinlock might cause a lockup if a secondary CPU was
disabled with such lock taken. Fix it here by checking if the
ring buffer spinlock is busy on Hyper-V framebuffer panic notifier;
if so, bail-out avoiding the potential lockup scenario.
Cc: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Cc: Dexuan Cui <decui@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Michael Kelley <mikelley@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: Tianyu Lan <Tianyu.Lan@microsoft.com>
Cc: Wei Liu <wei.liu@kernel.org>
Tested-by: Fabio A M Martins <fabiomirmar@gmail.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Link: https://lore.kernel.org/r/20220819221731.480795-10-gpiccoli@igalia.com
Signed-off-by: Wei Liu <wei.liu@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/hv/ring_buffer.c | 13 +++++++++++++
drivers/video/fbdev/hyperv_fb.c | 8 +++++++-
include/linux/hyperv.h | 2 ++
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index f4091143213b..1475ea77351e 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -249,6 +249,19 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info)
ring_info->pkt_buffer_size = 0;
}
+/*
+ * Check if the ring buffer spinlock is available to take or not; used on
+ * atomic contexts, like panic path (see the Hyper-V framebuffer driver).
+ */
+
+bool hv_ringbuffer_spinlock_busy(struct vmbus_channel *channel)
+{
+ struct hv_ring_buffer_info *rinfo = &channel->outbound;
+
+ return spin_is_locked(&rinfo->ring_lock);
+}
+EXPORT_SYMBOL_GPL(hv_ringbuffer_spinlock_busy);
+
/* Write to the ring buffer. */
int hv_ringbuffer_write(struct vmbus_channel *channel,
const struct kvec *kv_list, u32 kv_count,
diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c
index 58c304a3b7c4..de865e197c8d 100644
--- a/drivers/video/fbdev/hyperv_fb.c
+++ b/drivers/video/fbdev/hyperv_fb.c
@@ -799,12 +799,18 @@ static void hvfb_ondemand_refresh_throttle(struct hvfb_par *par,
static int hvfb_on_panic(struct notifier_block *nb,
unsigned long e, void *p)
{
+ struct hv_device *hdev;
struct hvfb_par *par;
struct fb_info *info;
par = container_of(nb, struct hvfb_par, hvfb_panic_nb);
- par->synchronous_fb = true;
info = par->info;
+ hdev = device_to_hv_device(info->device);
+
+ if (hv_ringbuffer_spinlock_busy(hdev->channel))
+ return NOTIFY_DONE;
+
+ par->synchronous_fb = true;
if (par->need_docopy)
hvfb_docopy(par, 0, dio_fb_size);
synthvid_update(info, 0, 0, INT_MAX, INT_MAX);
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index ddc8713ce57b..8499fc9220e0 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1307,6 +1307,8 @@ struct hv_ring_buffer_debug_info {
int hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
struct hv_ring_buffer_debug_info *debug_info);
+bool hv_ringbuffer_spinlock_busy(struct vmbus_channel *channel);
+
/* Vmbus interface */
#define vmbus_driver_register(driver) \
__vmbus_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
--
2.35.1
next prev parent reply other threads:[~2022-12-17 0:12 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-17 0:10 [PATCH AUTOSEL 5.15 1/5] rcu: Fix __this_cpu_read() lockdep warning in rcu_force_quiescent_state() Sasha Levin
2022-12-17 0:10 ` [PATCH AUTOSEL 5.15 2/5] arm64: make is_ttbrX_addr() noinstr-safe Sasha Levin
2022-12-17 0:10 ` Sasha Levin
2022-12-17 0:10 ` Sasha Levin [this message]
2022-12-17 0:10 ` [PATCH AUTOSEL 5.15 3/5] video: hyperv_fb: Avoid taking busy spinlock on panic path Sasha Levin
2022-12-17 0:10 ` [PATCH AUTOSEL 5.15 4/5] x86/hyperv: Remove unregister syscore call from Hyper-V cleanup Sasha Levin
2022-12-17 0:10 ` [PATCH AUTOSEL 5.15 5/5] binfmt_misc: fix shift-out-of-bounds in check_special_flags 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=20221217001038.41355-3-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=Tianyu.Lan@microsoft.com \
--cc=decui@microsoft.com \
--cc=deller@gmx.de \
--cc=dri-devel@lists.freedesktop.org \
--cc=fabiomirmar@gmail.com \
--cc=gpiccoli@igalia.com \
--cc=haiyangz@microsoft.com \
--cc=kys@microsoft.com \
--cc=linux-fbdev@vger.kernel.org \
--cc=linux-hyperv@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mikelley@microsoft.com \
--cc=parri.andrea@gmail.com \
--cc=stable@vger.kernel.org \
--cc=sthemmin@microsoft.com \
--cc=wei.liu@kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.