summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-10-20 14:33:15 -1000
committerLinus Torvalds <torvalds@linux-foundation.org>2026-10-20 14:33:15 -1000
commit2a0d3d73c112e1ffbb8cc01098b9bd2a3087b40f (patch)
treebf5dfa84478f1732ed98d56913dbb9086d0ae951 /drivers
parent742f62b63904cdc20a364a49d2861e32464a0af7 (diff)
parent61b6d1df1d6234c38a6ea7e4f58e7da035ef6ab4 (diff)
Merge tag 'for-linus-7.4-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull xen updates from Juergen Gross: "This time only small fixes and cleanups all over Xen related drivers. Nothing really stands out here" * tag 'for-linus-7.4-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen-blkfront: Fix IO race during unplug xen-pciback: Fix pcistub_device ref leak in pcistub_get_gsi_from_sbdf() xen/pcifront: check that an AER callback exists before calling it xen/gntdev: Fix gntdev_dmabuf ref leak in dmabuf_exp_wait_released() x86/PVH: don't truncate initrd address/size xen/privcmd: Only claim ioreqs matching an ioeventfd xen/scsifront: check for a NULL shadow entry on a backend response xen: fix typos in comments xen/gntdev: prevent private mappings from becoming writable xen: remove unused hvm_vcpu.h header xen-blkfront: unbind irq before tearing down ring and shadow requests xen/blkback: Prevent missed completion when draining I/O xen/pcifront: Fix PCI device reference leak in AER handling
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/xen-blkback/blkback.c7
-rw-r--r--drivers/block/xen-blkfront.c16
-rw-r--r--drivers/pci/xen-pcifront.c16
-rw-r--r--drivers/scsi/xen-scsifront.c2
-rw-r--r--drivers/xen/gntdev-dmabuf.c4
-rw-r--r--drivers/xen/gntdev.c7
-rw-r--r--drivers/xen/mcelog.c2
-rw-r--r--drivers/xen/privcmd.c47
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c7
9 files changed, 61 insertions, 47 deletions
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 7871099bc0d4..88526e349ce1 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -1021,6 +1021,13 @@ static void xen_blk_drain_io(struct xen_blkif_ring *ring)
struct xen_blkif *blkif = ring->blkif;
atomic_set(&blkif->drain, 1);
+ /*
+ * Publish drain before checking inflight. Otherwise,
+ * xen_blkbk_unmap_and_respond_callback() can decrement inflight with
+ * atomic_dec_and_test() and still see drain == 0 after this path saw
+ * inflight > 0, missing the completion.
+ */
+ smp_mb();
do {
if (atomic_read(&ring->inflight) == 0)
break;
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 8dad7bf5f664..ad0cb42c1019 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -1211,6 +1211,14 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
int i, j, segs;
/*
+ * Interrupt teardown must be done ahead of freeing queue-related
+ * data, otherwise the interrupt handler can race with the cleanup.
+ */
+ if (rinfo->irq)
+ unbind_from_irqhandler(rinfo->irq, rinfo);
+ rinfo->evtchn = rinfo->irq = 0;
+
+ /*
* Remove indirect pages, this only happens when using indirect
* descriptors but not persistent grants
*/
@@ -1292,10 +1300,6 @@ free_shadow:
/* Free resources associated with old device channel. */
xenbus_teardown_ring((void **)&rinfo->ring.sring, info->nr_ring_pages,
rinfo->ring_ref);
-
- if (rinfo->irq)
- unbind_from_irqhandler(rinfo->irq, rinfo);
- rinfo->evtchn = rinfo->irq = 0;
}
static void blkif_free(struct blkfront_info *info, int suspend)
@@ -2138,10 +2142,8 @@ static void blkfront_closing(struct blkfront_info *info)
return;
/* No more blkif_request(). */
- if (info->rq && info->gd) {
- blk_mq_stop_hw_queues(info->rq);
+ if (info->gd)
blk_mark_disk_dead(info->gd);
- }
for_each_rinfo(info, rinfo, i) {
/* No more gnttab callback work. */
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index cffc32d66032..b8f2921cc253 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -579,16 +579,15 @@ static pci_ers_result_t pcifront_common_process(int cmd,
int bus = pdev->sh_info->aer_op.bus;
int devfn = pdev->sh_info->aer_op.devfn;
int domain = pdev->sh_info->aer_op.domain;
- struct pci_dev *pcidev;
+ struct pci_dev *pcidev __free(pci_dev_put) =
+ pci_get_domain_bus_and_slot(domain, bus, devfn);
dev_dbg(&pdev->xdev->dev,
"pcifront AER process: cmd %x (bus:%x, devfn%x)",
cmd, bus, devfn);
- pcidev = pci_get_domain_bus_and_slot(domain, bus, devfn);
if (!pcidev || !pcidev->dev.driver) {
dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n");
- pci_dev_put(pcidev);
return PCI_ERS_RESULT_NONE;
}
pdrv = to_pci_driver(pcidev->dev.driver);
@@ -599,11 +598,16 @@ static pci_ers_result_t pcifront_common_process(int cmd,
case XEN_PCI_OP_aer_detected:
return pdrv->err_handler->error_detected(pcidev, state);
case XEN_PCI_OP_aer_mmio:
- return pdrv->err_handler->mmio_enabled(pcidev);
+ if (pdrv->err_handler->mmio_enabled)
+ return pdrv->err_handler->mmio_enabled(pcidev);
+ return PCI_ERS_RESULT_RECOVERED;
case XEN_PCI_OP_aer_slotreset:
- return pdrv->err_handler->slot_reset(pcidev);
+ if (pdrv->err_handler->slot_reset)
+ return pdrv->err_handler->slot_reset(pcidev);
+ return PCI_ERS_RESULT_RECOVERED;
case XEN_PCI_OP_aer_resume:
- pdrv->err_handler->resume(pcidev);
+ if (pdrv->err_handler->resume)
+ pdrv->err_handler->resume(pcidev);
return PCI_ERS_RESULT_NONE;
default:
dev_err(&pdev->xdev->dev,
diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c
index aa44a233eac8..9d7e12e40089 100644
--- a/drivers/scsi/xen-scsifront.c
+++ b/drivers/scsi/xen-scsifront.c
@@ -1077,7 +1077,7 @@ static void scsifront_do_lun_hotplug(struct vscsifrnt_info *info, int op)
/*
* Front device state path, used in sdev_configure called
- * on successfull scsi_add_device, and in sdev_destroy called
+ * on successful scsi_add_device, and in sdev_destroy called
* on remove of a device.
*/
snprintf(info->dev_state_path, sizeof(info->dev_state_path),
diff --git a/drivers/xen/gntdev-dmabuf.c b/drivers/xen/gntdev-dmabuf.c
index 83b0df460894..df1883aca850 100644
--- a/drivers/xen/gntdev-dmabuf.c
+++ b/drivers/xen/gntdev-dmabuf.c
@@ -96,8 +96,10 @@ dmabuf_exp_wait_obj_new(struct gntdev_dmabuf_priv *priv,
struct gntdev_dmabuf_wait_obj *obj;
obj = kzalloc_obj(*obj);
- if (!obj)
+ if (!obj) {
+ kref_put(&gntdev_dmabuf->u.exp.refcount, dmabuf_exp_release);
return ERR_PTR(-ENOMEM);
+ }
init_completion(&obj->completion);
obj->gntdev_dmabuf = gntdev_dmabuf;
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 1dcc4675580e..b71f5bae25b6 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -1066,6 +1066,13 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED))
return -EINVAL;
+ /*
+ * Private mappings of foreign grant pages must never become
+ * writable: they would take the COW path on granted pages.
+ */
+ if (!(vma->vm_flags & VM_SHARED))
+ vm_flags_clear(vma, VM_MAYWRITE);
+
pr_debug("map %d+%d at %lx (pgoff %lx)\n",
index, count, vma->vm_start, vma->vm_pgoff);
diff --git a/drivers/xen/mcelog.c b/drivers/xen/mcelog.c
index 32ab419bb503..f19cc7a67f36 100644
--- a/drivers/xen/mcelog.c
+++ b/drivers/xen/mcelog.c
@@ -1,6 +1,6 @@
/******************************************************************************
* mcelog.c
- * Driver for receiving and transferring machine check error infomation
+ * Driver for receiving and transferring machine check error information
*
* Copyright (c) 2012 Intel Corporation
* Author: Liu, Jinsong <jinsong.liu@intel.com>
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 7cfc28f1bb86..c67ec6d282cf 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -1169,51 +1169,40 @@ static irqreturn_t ioeventfd_interrupt(int irq, void *dev_id)
struct privcmd_kernel_ioreq *kioreq = port->kioreq;
struct ioreq *ioreq = &kioreq->ioreq[port->vcpu];
struct privcmd_kernel_ioeventfd *kioeventfd;
- unsigned int state = STATE_IOREQ_READY;
+ bool matched = false;
- if (ioreq->state != STATE_IOREQ_READY ||
- ioreq->type != IOREQ_TYPE_COPY || ioreq->dir != IOREQ_WRITE)
+ if (ioreq->state != STATE_IOREQ_READY)
return IRQ_NONE;
- /*
- * We need a barrier, smp_mb(), here to ensure reads are finished before
- * `state` is updated. Since the lock implementation ensures that
- * appropriate barrier will be added anyway, we can avoid adding
- * explicit barrier here.
- *
- * Ideally we don't need to update `state` within the locks, but we do
- * that here to avoid adding explicit barrier.
- */
+ /* Xen publishes the request before changing its state to READY. */
+ virt_rmb();
- spin_lock(&kioreq->lock);
- ioreq->state = STATE_IOREQ_INPROCESS;
+ if (ioreq->type != IOREQ_TYPE_COPY || ioreq->dir != IOREQ_WRITE)
+ return IRQ_NONE;
+ spin_lock(&kioreq->lock);
list_for_each_entry(kioeventfd, &kioreq->ioeventfds, list) {
if (ioreq->addr == kioeventfd->addr + VIRTIO_MMIO_QUEUE_NOTIFY &&
ioreq->size == kioeventfd->addr_len &&
(ioreq->data & QUEUE_NOTIFY_VQ_MASK) == kioeventfd->vq) {
+ /* Finish reading the request before claiming it. */
+ virt_mb();
+ ioreq->state = STATE_IOREQ_INPROCESS;
eventfd_signal(kioeventfd->eventfd);
- state = STATE_IORESP_READY;
+ matched = true;
break;
}
}
spin_unlock(&kioreq->lock);
- /*
- * We need a barrier, smp_mb(), here to ensure writes are finished
- * before `state` is updated. Since the lock implementation ensures that
- * appropriate barrier will be added anyway, we can avoid adding
- * explicit barrier here.
- */
-
- ioreq->state = state;
-
- if (state == STATE_IORESP_READY) {
- notify_remote_via_evtchn(port->port);
- return IRQ_HANDLED;
- }
+ if (!matched)
+ return IRQ_NONE;
- return IRQ_NONE;
+ /* Publish the response only after signaling the eventfd. */
+ virt_wmb();
+ ioreq->state = STATE_IORESP_READY;
+ notify_remote_via_evtchn(port->port);
+ return IRQ_HANDLED;
}
static void ioreq_free(struct privcmd_kernel_ioreq *kioreq)
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 79a2b5dfd694..d1a335233aab 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -234,13 +234,16 @@ static int pcistub_get_gsi_from_sbdf(unsigned int sbdf)
int bus = PCI_BUS_NUM(sbdf);
int slot = PCI_SLOT(sbdf);
int func = PCI_FUNC(sbdf);
+ int gsi;
psdev = pcistub_device_find(domain, bus, slot, func);
-
if (!psdev)
return -ENODEV;
- return psdev->gsi;
+ gsi = psdev->gsi;
+ pcistub_device_put(psdev);
+
+ return gsi;
}
#endif