diff --git a/arch/x86/platform/pvh/enlighten.c b/arch/x86/platform/pvh/enlighten.c index cb442cbd9d82..88632c661430 100644 --- a/arch/x86/platform/pvh/enlighten.c +++ b/arch/x86/platform/pvh/enlighten.c @@ -79,7 +79,9 @@ static void __init init_pvh_bootparams(bool xen_guest) struct hvm_modlist_entry *modaddr = __va(pvh_start_info.modlist_paddr); pvh_bootparams.hdr.ramdisk_image = modaddr->paddr; + pvh_bootparams.ext_ramdisk_image = modaddr->paddr >> 32; pvh_bootparams.hdr.ramdisk_size = modaddr->size; + pvh_bootparams.ext_ramdisk_size = modaddr->size >> 32; } /* 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 @@ -1210,6 +1210,14 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo) struct blkfront_info *info = rinfo->dev_info; 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 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo) /* 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 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(); + + if (ioreq->type != IOREQ_TYPE_COPY || ioreq->dir != IOREQ_WRITE) + return IRQ_NONE; spin_lock(&kioreq->lock); - ioreq->state = STATE_IOREQ_INPROCESS; - 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. - */ + if (!matched) + return IRQ_NONE; - ioreq->state = state; - - if (state == STATE_IORESP_READY) { - notify_remote_via_evtchn(port->port); - return IRQ_HANDLED; - } - - 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 diff --git a/include/xen/interface/hvm/hvm_vcpu.h b/include/xen/interface/hvm/hvm_vcpu.h deleted file mode 100644 index cbf93493275c..000000000000 --- a/include/xen/interface/hvm/hvm_vcpu.h +++ /dev/null @@ -1,116 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright (c) 2015, Roger Pau Monne - */ - -#ifndef __XEN_PUBLIC_HVM_HVM_VCPU_H__ -#define __XEN_PUBLIC_HVM_HVM_VCPU_H__ - -#include "../xen.h" - -struct vcpu_hvm_x86_32 { - uint32_t eax; - uint32_t ecx; - uint32_t edx; - uint32_t ebx; - uint32_t esp; - uint32_t ebp; - uint32_t esi; - uint32_t edi; - uint32_t eip; - uint32_t eflags; - - uint32_t cr0; - uint32_t cr3; - uint32_t cr4; - - uint32_t pad1; - - /* - * EFER should only be used to set the NXE bit (if required) - * when starting a vCPU in 32bit mode with paging enabled or - * to set the LME/LMA bits in order to start the vCPU in - * compatibility mode. - */ - uint64_t efer; - - uint32_t cs_base; - uint32_t ds_base; - uint32_t ss_base; - uint32_t es_base; - uint32_t tr_base; - uint32_t cs_limit; - uint32_t ds_limit; - uint32_t ss_limit; - uint32_t es_limit; - uint32_t tr_limit; - uint16_t cs_ar; - uint16_t ds_ar; - uint16_t ss_ar; - uint16_t es_ar; - uint16_t tr_ar; - - uint16_t pad2[3]; -}; - -/* - * The layout of the _ar fields of the segment registers is the - * following: - * - * Bits [0,3]: type (bits 40-43). - * Bit 4: s (descriptor type, bit 44). - * Bit [5,6]: dpl (descriptor privilege level, bits 45-46). - * Bit 7: p (segment-present, bit 47). - * Bit 8: avl (available for system software, bit 52). - * Bit 9: l (64-bit code segment, bit 53). - * Bit 10: db (meaning depends on the segment, bit 54). - * Bit 11: g (granularity, bit 55) - * Bits [12,15]: unused, must be blank. - * - * A more complete description of the meaning of this fields can be - * obtained from the Intel SDM, Volume 3, section 3.4.5. - */ - -struct vcpu_hvm_x86_64 { - uint64_t rax; - uint64_t rcx; - uint64_t rdx; - uint64_t rbx; - uint64_t rsp; - uint64_t rbp; - uint64_t rsi; - uint64_t rdi; - uint64_t rip; - uint64_t rflags; - - uint64_t cr0; - uint64_t cr3; - uint64_t cr4; - uint64_t efer; - - /* - * Using VCPU_HVM_MODE_64B implies that the vCPU is launched - * directly in long mode, so the cached parts of the segment - * registers get set to match that environment. - * - * If the user wants to launch the vCPU in compatibility mode - * the 32-bit structure should be used instead. - */ -}; - -struct vcpu_hvm_context { -#define VCPU_HVM_MODE_32B 0 /* 32bit fields of the structure will be used. */ -#define VCPU_HVM_MODE_64B 1 /* 64bit fields of the structure will be used. */ - uint32_t mode; - - uint32_t pad; - - /* CPU registers. */ - union { - struct vcpu_hvm_x86_32 x86_32; - struct vcpu_hvm_x86_64 x86_64; - } cpu_regs; -}; -typedef struct vcpu_hvm_context vcpu_hvm_context_t; - -#endif /* __XEN_PUBLIC_HVM_HVM_VCPU_H__ */ diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h index 79a443c65ea9..462e36392a9f 100644 --- a/include/xen/interface/platform.h +++ b/include/xen/interface/platform.h @@ -421,10 +421,10 @@ struct xenpf_pcpuinfo { /* IN */ uint32_t xen_cpuid; /* OUT */ - /* The maxium cpu_id that is present */ + /* The maximum cpu_id that is present */ uint32_t max_present; #define XEN_PCPU_FLAGS_ONLINE 1 - /* Correponding xen_cpuid is not present*/ + /* Corresponding xen_cpuid is not present*/ #define XEN_PCPU_FLAGS_INVALID 2 uint32_t flags; uint32_t apic_id; diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h index 40c9793e9880..f9acb21875cf 100644 --- a/include/xen/interface/xen.h +++ b/include/xen/interface/xen.h @@ -94,7 +94,7 @@ #define VIRQ_XENOPROF 7 /* V. XenOprofile interrupt: new sample available */ #define VIRQ_CON_RING 8 /* G. (DOM0) Bytes received on console */ #define VIRQ_PCPU_STATE 9 /* G. (DOM0) PCPU state changed */ -#define VIRQ_MEM_EVENT 10 /* G. (DOM0) A memory event has occured */ +#define VIRQ_MEM_EVENT 10 /* G. (DOM0) A memory event has occurred */ #define VIRQ_XC_RESERVED 11 /* G. Reserved for XenClient */ #define VIRQ_ENOMEM 12 /* G. (DOM0) Low on heap memory */ #define VIRQ_XENPMU 13 /* PMC interrupt */ diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h index 8ca15743af7f..6424c5cf8ef5 100644 --- a/include/xen/xenbus.h +++ b/include/xen/xenbus.h @@ -63,7 +63,7 @@ struct xenbus_watch unsigned int nr_pending; /* - * Called just before enqueing new event while a spinlock is held. + * Called just before enqueuing new event while a spinlock is held. * The event will be discarded if this callback returns false. */ bool (*will_handle)(struct xenbus_watch *,