diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 2fc74f4738f6..06d930c12ab8 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -187,6 +187,8 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq) sg_init_one(&sg, vb->pfns, sizeof(vb->pfns[0]) * vb->num_pfns); + post_page_relinquish_tlb_inv(); + /* We should always be able to add one buffer to an empty queue. */ virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL); virtqueue_kick(vq); @@ -219,6 +221,8 @@ static int virtballoon_free_page_report(struct page_reporting_dev_info *pr_dev_i if (WARN_ON_ONCE(err)) return err; + post_page_relinquish_tlb_inv(); + virtqueue_kick(vq); /* When host has read buffer, this completes via balloon_ack */ diff --git a/include/linux/virtio_balloon.h b/include/linux/virtio_balloon.h index 032596592679..e7fe377b049c 100644 --- a/include/linux/virtio_balloon.h +++ b/include/linux/virtio_balloon.h @@ -16,6 +16,7 @@ struct page; struct virtio_balloon_hyp_ops { bool (*page_relinquish_disallowed)(void); void (*page_relinquish)(struct page *page, unsigned int nr); + void (*post_page_relinquish_tlb_inv)(void); }; extern struct virtio_balloon_hyp_ops *virtio_balloon_hyp_ops; @@ -35,10 +36,17 @@ static inline void page_relinquish(struct page *page, unsigned int nr) return virtio_balloon_hyp_ops->page_relinquish(page, nr); } +static inline void post_page_relinquish_tlb_inv(void) +{ + if (virtio_balloon_hyp_ops && + virtio_balloon_hyp_ops->post_page_relinquish_tlb_inv) + return virtio_balloon_hyp_ops->post_page_relinquish_tlb_inv(); +} #else /* !CONFIG_VIRTIO_BALLOON_HYP_OPS */ static inline bool page_relinquish_disallowed(void) { return false; } static inline void page_relinquish(struct page *page, unsigned int nr) { } +static inline void post_page_relinquish_tlb_inv(void) { } #endif /* CONFIG_VIRTIO_BALLOON_HYP_OPS */