* [PATCH 0/2] Improvements to virtio_balloon pm
@ 2024-03-18 9:10 David Stevens
2024-03-18 9:10 ` [PATCH 1/2] virtio_balloon: Give the balloon its own wakeup source David Stevens
2024-03-18 9:10 ` [PATCH 2/2] virtio_balloon: Treat stats requests as wakeup events David Stevens
0 siblings, 2 replies; 5+ messages in thread
From: David Stevens @ 2024-03-18 9:10 UTC (permalink / raw)
To: Michael S . Tsirkin, David Hildenbrand
Cc: virtualization, linux-kernel, David Stevens
From: David Stevens <stevensd@chromium.org>
The virtio_balloon driver uses wakeup sources to allow the guest to
enter system power management sleep states (e.g. s2idle) without running
the risk of becoming unresponsive to cooperative memory management
requests from the host. This series fixes an issue where wakeup sources
for inflate/deflate were improperly shared between drivers. It also
closes a race where stats requests that come in immediately before a
sleep state transition could fail to be handled in a timely manner.
David Stevens (2):
virtio_balloon: Give the balloon its own wakeup source
virtio_balloon: Treat stats requests as wakeup events
drivers/virtio/virtio_balloon.c | 76 ++++++++++++++++++++-------------
1 file changed, 47 insertions(+), 29 deletions(-)
base-commit: e8f897f4afef0031fe618a8e94127a0934896aba
--
2.44.0.291.gc1ea87d7ee-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] virtio_balloon: Give the balloon its own wakeup source
2024-03-18 9:10 [PATCH 0/2] Improvements to virtio_balloon pm David Stevens
@ 2024-03-18 9:10 ` David Stevens
2024-03-19 8:44 ` David Hildenbrand
2024-03-18 9:10 ` [PATCH 2/2] virtio_balloon: Treat stats requests as wakeup events David Stevens
1 sibling, 1 reply; 5+ messages in thread
From: David Stevens @ 2024-03-18 9:10 UTC (permalink / raw)
To: Michael S . Tsirkin, David Hildenbrand
Cc: virtualization, linux-kernel, David Stevens
From: David Stevens <stevensd@chromium.org>
Wakeup sources don't support nesting multiple events, so sharing a
single object between multiple drivers can result in one driver
overriding the wakeup event processing period specified by another
driver. Have the virtio balloon driver use the wakeup source of the
device it is bound to rather than the wakeup source of the parent
device, to avoid conflicts with the transport layer.
Note that although the virtio balloon's virtio_device itself isn't what
actually wakes up the device, it is responsible for processing wakeup
events. In the same way that EPOLLWAKEUP uses a dedicated wakeup_source
to prevent suspend when userspace is processing wakeup events, a
dedicated wakeup_source is necessary when processing wakeup events in a
higher layer in the kernel.
Fixes: b12fbc3f787e ("virtio_balloon: stay awake while adjusting balloon")
Signed-off-by: David Stevens <stevensd@chromium.org>
---
drivers/virtio/virtio_balloon.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 1f5b3dd31fcf..7fe7ef5f1c77 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -450,7 +450,7 @@ static void start_update_balloon_size(struct virtio_balloon *vb)
vb->adjustment_signal_pending = true;
if (!vb->adjustment_in_progress) {
vb->adjustment_in_progress = true;
- pm_stay_awake(vb->vdev->dev.parent);
+ pm_stay_awake(&vb->vdev->dev);
}
spin_unlock_irqrestore(&vb->adjustment_lock, flags);
@@ -462,7 +462,7 @@ static void end_update_balloon_size(struct virtio_balloon *vb)
spin_lock_irq(&vb->adjustment_lock);
if (!vb->adjustment_signal_pending && vb->adjustment_in_progress) {
vb->adjustment_in_progress = false;
- pm_relax(vb->vdev->dev.parent);
+ pm_relax(&vb->vdev->dev);
}
spin_unlock_irq(&vb->adjustment_lock);
}
@@ -1028,6 +1028,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
}
spin_lock_init(&vb->adjustment_lock);
+ device_set_wakeup_capable(&vb->vdev->dev, true);
virtio_device_ready(vdev);
--
2.44.0.291.gc1ea87d7ee-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] virtio_balloon: Treat stats requests as wakeup events
2024-03-18 9:10 [PATCH 0/2] Improvements to virtio_balloon pm David Stevens
2024-03-18 9:10 ` [PATCH 1/2] virtio_balloon: Give the balloon its own wakeup source David Stevens
@ 2024-03-18 9:10 ` David Stevens
2024-03-19 8:54 ` David Hildenbrand
1 sibling, 1 reply; 5+ messages in thread
From: David Stevens @ 2024-03-18 9:10 UTC (permalink / raw)
To: Michael S . Tsirkin, David Hildenbrand
Cc: virtualization, linux-kernel, David Stevens
From: David Stevens <stevensd@chromium.org>
Treat stats requests as wakeup events to ensure that the driver responds
to device requests in a timely manner.
Signed-off-by: David Stevens <stevensd@chromium.org>
---
drivers/virtio/virtio_balloon.c | 75 ++++++++++++++++++++-------------
1 file changed, 46 insertions(+), 29 deletions(-)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 7fe7ef5f1c77..402dec98e08c 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -121,11 +121,14 @@ struct virtio_balloon {
struct page_reporting_dev_info pr_dev_info;
/* State for keeping the wakeup_source active while adjusting the balloon */
- spinlock_t adjustment_lock;
- bool adjustment_signal_pending;
- bool adjustment_in_progress;
+ spinlock_t wakeup_lock;
+ bool processing_wakeup_event;
+ u32 wakeup_signal_mask;
};
+#define ADJUSTMENT_WAKEUP_SIGNAL (1 << 0)
+#define STATS_WAKEUP_SIGNAL (1 << 1)
+
static const struct virtio_device_id id_table[] = {
{ VIRTIO_ID_BALLOON, VIRTIO_DEV_ANY_ID },
{ 0 },
@@ -140,6 +143,36 @@ static u32 page_to_balloon_pfn(struct page *page)
return pfn * VIRTIO_BALLOON_PAGES_PER_PAGE;
}
+static void start_wakeup_event(struct virtio_balloon *vb, u32 mask)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&vb->wakeup_lock, flags);
+ vb->wakeup_signal_mask |= mask;
+ if (!vb->processing_wakeup_event) {
+ vb->processing_wakeup_event = true;
+ pm_stay_awake(&vb->vdev->dev);
+ }
+ spin_unlock_irqrestore(&vb->wakeup_lock, flags);
+}
+
+static void process_wakeup_event(struct virtio_balloon *vb, u32 mask)
+{
+ spin_lock_irq(&vb->wakeup_lock);
+ vb->wakeup_signal_mask &= ~mask;
+ spin_unlock_irq(&vb->wakeup_lock);
+}
+
+static void finish_wakeup_event(struct virtio_balloon *vb)
+{
+ spin_lock_irq(&vb->wakeup_lock);
+ if (!vb->wakeup_signal_mask && vb->processing_wakeup_event) {
+ vb->processing_wakeup_event = false;
+ pm_relax(&vb->vdev->dev);
+ }
+ spin_unlock_irq(&vb->wakeup_lock);
+}
+
static void balloon_ack(struct virtqueue *vq)
{
struct virtio_balloon *vb = vq->vdev->priv;
@@ -370,8 +403,10 @@ static void stats_request(struct virtqueue *vq)
struct virtio_balloon *vb = vq->vdev->priv;
spin_lock(&vb->stop_update_lock);
- if (!vb->stop_update)
+ if (!vb->stop_update) {
+ start_wakeup_event(vb, STATS_WAKEUP_SIGNAL);
queue_work(system_freezable_wq, &vb->update_balloon_stats_work);
+ }
spin_unlock(&vb->stop_update_lock);
}
@@ -444,29 +479,10 @@ static void virtio_balloon_queue_free_page_work(struct virtio_balloon *vb)
static void start_update_balloon_size(struct virtio_balloon *vb)
{
- unsigned long flags;
-
- spin_lock_irqsave(&vb->adjustment_lock, flags);
- vb->adjustment_signal_pending = true;
- if (!vb->adjustment_in_progress) {
- vb->adjustment_in_progress = true;
- pm_stay_awake(&vb->vdev->dev);
- }
- spin_unlock_irqrestore(&vb->adjustment_lock, flags);
-
+ start_wakeup_event(vb, ADJUSTMENT_WAKEUP_SIGNAL);
queue_work(system_freezable_wq, &vb->update_balloon_size_work);
}
-static void end_update_balloon_size(struct virtio_balloon *vb)
-{
- spin_lock_irq(&vb->adjustment_lock);
- if (!vb->adjustment_signal_pending && vb->adjustment_in_progress) {
- vb->adjustment_in_progress = false;
- pm_relax(&vb->vdev->dev);
- }
- spin_unlock_irq(&vb->adjustment_lock);
-}
-
static void virtballoon_changed(struct virtio_device *vdev)
{
struct virtio_balloon *vb = vdev->priv;
@@ -495,7 +511,10 @@ static void update_balloon_stats_func(struct work_struct *work)
vb = container_of(work, struct virtio_balloon,
update_balloon_stats_work);
+
+ process_wakeup_event(vb, STATS_WAKEUP_SIGNAL);
stats_handle_request(vb);
+ finish_wakeup_event(vb);
}
static void update_balloon_size_func(struct work_struct *work)
@@ -506,9 +525,7 @@ static void update_balloon_size_func(struct work_struct *work)
vb = container_of(work, struct virtio_balloon,
update_balloon_size_work);
- spin_lock_irq(&vb->adjustment_lock);
- vb->adjustment_signal_pending = false;
- spin_unlock_irq(&vb->adjustment_lock);
+ process_wakeup_event(vb, ADJUSTMENT_WAKEUP_SIGNAL);
diff = towards_target(vb);
@@ -523,7 +540,7 @@ static void update_balloon_size_func(struct work_struct *work)
if (diff)
queue_work(system_freezable_wq, work);
else
- end_update_balloon_size(vb);
+ finish_wakeup_event(vb);
}
static int init_vqs(struct virtio_balloon *vb)
@@ -1027,7 +1044,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
goto out_unregister_oom;
}
- spin_lock_init(&vb->adjustment_lock);
+ spin_lock_init(&vb->wakeup_lock);
device_set_wakeup_capable(&vb->vdev->dev, true);
virtio_device_ready(vdev);
--
2.44.0.291.gc1ea87d7ee-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] virtio_balloon: Give the balloon its own wakeup source
2024-03-18 9:10 ` [PATCH 1/2] virtio_balloon: Give the balloon its own wakeup source David Stevens
@ 2024-03-19 8:44 ` David Hildenbrand
0 siblings, 0 replies; 5+ messages in thread
From: David Hildenbrand @ 2024-03-19 8:44 UTC (permalink / raw)
To: David Stevens, Michael S . Tsirkin; +Cc: virtualization, linux-kernel
On 18.03.24 10:10, David Stevens wrote:
> From: David Stevens <stevensd@chromium.org>
>
> Wakeup sources don't support nesting multiple events, so sharing a
> single object between multiple drivers can result in one driver
> overriding the wakeup event processing period specified by another
> driver. Have the virtio balloon driver use the wakeup source of the
> device it is bound to rather than the wakeup source of the parent
> device, to avoid conflicts with the transport layer.
>
> Note that although the virtio balloon's virtio_device itself isn't what
> actually wakes up the device, it is responsible for processing wakeup
> events. In the same way that EPOLLWAKEUP uses a dedicated wakeup_source
> to prevent suspend when userspace is processing wakeup events, a
> dedicated wakeup_source is necessary when processing wakeup events in a
> higher layer in the kernel.
>
> Fixes: b12fbc3f787e ("virtio_balloon: stay awake while adjusting balloon")
> Signed-off-by: David Stevens <stevensd@chromium.org>
> ---
> drivers/virtio/virtio_balloon.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
> index 1f5b3dd31fcf..7fe7ef5f1c77 100644
> --- a/drivers/virtio/virtio_balloon.c
> +++ b/drivers/virtio/virtio_balloon.c
> @@ -450,7 +450,7 @@ static void start_update_balloon_size(struct virtio_balloon *vb)
> vb->adjustment_signal_pending = true;
> if (!vb->adjustment_in_progress) {
> vb->adjustment_in_progress = true;
> - pm_stay_awake(vb->vdev->dev.parent);
> + pm_stay_awake(&vb->vdev->dev);
> }
> spin_unlock_irqrestore(&vb->adjustment_lock, flags);
>
> @@ -462,7 +462,7 @@ static void end_update_balloon_size(struct virtio_balloon *vb)
> spin_lock_irq(&vb->adjustment_lock);
> if (!vb->adjustment_signal_pending && vb->adjustment_in_progress) {
> vb->adjustment_in_progress = false;
> - pm_relax(vb->vdev->dev.parent);
> + pm_relax(&vb->vdev->dev);
> }
> spin_unlock_irq(&vb->adjustment_lock);
> }
> @@ -1028,6 +1028,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
> }
>
> spin_lock_init(&vb->adjustment_lock);
Can we add a comment here why we have to do that?
> + device_set_wakeup_capable(&vb->vdev->dev, true);
>
> virtio_device_ready(vdev);
>
Absolutely not an expert on the details, but I assume this is fine.
Acked-by: David Hildenbrand <david@redhat.com>
--
Cheers,
David / dhildenb
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] virtio_balloon: Treat stats requests as wakeup events
2024-03-18 9:10 ` [PATCH 2/2] virtio_balloon: Treat stats requests as wakeup events David Stevens
@ 2024-03-19 8:54 ` David Hildenbrand
0 siblings, 0 replies; 5+ messages in thread
From: David Hildenbrand @ 2024-03-19 8:54 UTC (permalink / raw)
To: David Stevens, Michael S . Tsirkin; +Cc: virtualization, linux-kernel
On 18.03.24 10:10, David Stevens wrote:
> From: David Stevens <stevensd@chromium.org>
>
> Treat stats requests as wakeup events to ensure that the driver responds
> to device requests in a timely manner.
>
> Signed-off-by: David Stevens <stevensd@chromium.org>
> ---
> drivers/virtio/virtio_balloon.c | 75 ++++++++++++++++++++-------------
> 1 file changed, 46 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
> index 7fe7ef5f1c77..402dec98e08c 100644
> --- a/drivers/virtio/virtio_balloon.c
> +++ b/drivers/virtio/virtio_balloon.c
> @@ -121,11 +121,14 @@ struct virtio_balloon {
> struct page_reporting_dev_info pr_dev_info;
>
> /* State for keeping the wakeup_source active while adjusting the balloon */
> - spinlock_t adjustment_lock;
> - bool adjustment_signal_pending;
> - bool adjustment_in_progress;
> + spinlock_t wakeup_lock;
> + bool processing_wakeup_event;
> + u32 wakeup_signal_mask;
> };
>
> +#define ADJUSTMENT_WAKEUP_SIGNAL (1 << 0)
> +#define STATS_WAKEUP_SIGNAL (1 << 1)
I'd suggest a different naming like:
VIRTIO_BALLOON_WAKEUP_SIGNAL_ADJUST
VIRTIO_BALLOON_WAKEUP_SIGNAL_STATS
Apart from that, nothing jumped at me.
Acked-by: David Hildenbrand <david@redhat.com>
--
Cheers,
David / dhildenb
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-03-19 8:54 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-18 9:10 [PATCH 0/2] Improvements to virtio_balloon pm David Stevens
2024-03-18 9:10 ` [PATCH 1/2] virtio_balloon: Give the balloon its own wakeup source David Stevens
2024-03-19 8:44 ` David Hildenbrand
2024-03-18 9:10 ` [PATCH 2/2] virtio_balloon: Treat stats requests as wakeup events David Stevens
2024-03-19 8:54 ` David Hildenbrand
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).