Re: [PULL] uaccess: fix sparse warning on get/put_user for bitwise types
On Wednesday 14 January 2015 19:36:18 Michael S. Tsirkin wrote: As you asked, here's a pull request. This has been in linux-next apparently with no ill effects. The following changes since commit 99975cc6ada0d5f2675e83abecae05aba5f437d2: vhost/net: length miscalculation (2015-01-07 12:22:00 +0200) are available in the git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git tags/uaccess_for_upstream for you to fetch changes up to 0795cb1b46e7938ed679ccd48f933e75272b30e3: Pulled into my asm-generic now, thanks! Arnd ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH] VMCI: Fix two UVA mapping bugs
From: Jorgen Hansen jhan...@vmware.com (this is a resend of this patch. Originally sent last year, but post appears to have been lost) This change fixes two bugs in the VMCI host driver related to mapping the notify boolean from user space into kernel space: - the actual UVA was rounded up to the next page boundary - resulting in memory corruption in the calling process whenever notifications would be signalled. This has been fixed by just removing the PAGE_ALIGN part, since get_user_pages_fast can figure this out on its own - the mapped page wasn't stored anywhere, so it wasn't unmapped and put back when a VMCI context was destroyed. Fixed this by remembering the page. Acked-by: Andy King ack...@vmware.com Acked-by: Darius Davis dar...@vmware.com Signed-off-by: Jorgen Hansen jhan...@vmware.com --- drivers/misc/vmw_vmci/vmci_driver.c |2 +- drivers/misc/vmw_vmci/vmci_host.c | 13 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/misc/vmw_vmci/vmci_driver.c b/drivers/misc/vmw_vmci/vmci_driver.c index 3dee7ae..032d35c 100644 --- a/drivers/misc/vmw_vmci/vmci_driver.c +++ b/drivers/misc/vmw_vmci/vmci_driver.c @@ -113,5 +113,5 @@ module_exit(vmci_drv_exit); MODULE_AUTHOR(VMware, Inc.); MODULE_DESCRIPTION(VMware Virtual Machine Communication Interface.); -MODULE_VERSION(1.1.0.0-k); +MODULE_VERSION(1.1.1.0-k); MODULE_LICENSE(GPL v2); diff --git a/drivers/misc/vmw_vmci/vmci_host.c b/drivers/misc/vmw_vmci/vmci_host.c index 1723a6e..66fc992 100644 --- a/drivers/misc/vmw_vmci/vmci_host.c +++ b/drivers/misc/vmw_vmci/vmci_host.c @@ -218,13 +218,12 @@ static int drv_cp_harray_to_user(void __user *user_buf_uva, } /* - * Sets up a given context for notify to work. Calls drv_map_bool_ptr() - * which maps the notify boolean in user VA in kernel space. + * Sets up a given context for notify to work. Maps the notify + * boolean in user VA into kernel space. */ static int vmci_host_setup_notify(struct vmci_ctx *context, unsigned long uva) { - struct page *page; int retval; if (context-notify_page) { @@ -243,14 +242,16 @@ static int vmci_host_setup_notify(struct vmci_ctx *context, /* * Lock physical page backing a given user VA. */ - retval = get_user_pages_fast(PAGE_ALIGN(uva), 1, 1, page); - if (retval != 1) + retval = get_user_pages_fast(uva, 1, 1, context-notify_page); + if (retval != 1) { + context-notify_page = NULL; return VMCI_ERROR_GENERIC; + } /* * Map the locked page and set up notify pointer. */ - context-notify = kmap(page) + (uva (PAGE_SIZE - 1)); + context-notify = kmap(context-notify_page) + (uva (PAGE_SIZE - 1)); vmci_ctx_check_signal_notify(context); return VMCI_SUCCESS; -- 1.7.0 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v3 05/16] virtio/net: verify device has config space
Some devices might not implement config space access (e.g. remoteproc used not to - before 3.9). virtio/net needs config space access so make it fail gracefully if not there. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/net/virtio_net.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 5ca9771..9bc1072 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1713,6 +1713,12 @@ static int virtnet_probe(struct virtio_device *vdev) struct virtnet_info *vi; u16 max_queue_pairs; + if (!vdev-config-get) { + dev_err(vdev-dev, %s failure: config access disabled\n, + __func__); + return -EINVAL; + } + if (!virtnet_validate_features(vdev)) return -EINVAL; -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v3 02/16] virtio/9p: verify device has config space
Some devices might not implement config space access (e.g. remoteproc used not to - before 3.9). virtio/9p needs config space access so make it fail gracefully if not there. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- net/9p/trans_virtio.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index daa749c..d8e376a 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -524,6 +524,12 @@ static int p9_virtio_probe(struct virtio_device *vdev) int err; struct virtio_chan *chan; + if (!vdev-config-get) { + dev_err(vdev-dev, %s failure: config access disabled\n, + __func__); + return -EINVAL; + } + chan = kmalloc(sizeof(struct virtio_chan), GFP_KERNEL); if (!chan) { pr_err(Failed to allocate virtio 9P channel\n); -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v3 13/16] virtio_pci: modern driver
Lightly tested against qemu. One thing *not* implemented here is separate mappings for descriptor/avail/used rings. That's nice to have, will be done later after we have core support. This also exposes the PCI layout to userspace, and adds macros for PCI layout offsets: QEMU wants it, so why not? Trust, but verify. Signed-off-by: Rusty Russell ru...@rustcorp.com.au Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/virtio/virtio_pci_common.h | 25 +- drivers/virtio/virtio_pci_common.c | 14 +- drivers/virtio/virtio_pci_modern.c | 592 + drivers/virtio/Makefile| 2 +- 4 files changed, 627 insertions(+), 6 deletions(-) create mode 100644 drivers/virtio/virtio_pci_modern.c diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h index 2b1e70d..610c43f 100644 --- a/drivers/virtio/virtio_pci_common.h +++ b/drivers/virtio/virtio_pci_common.h @@ -53,12 +53,29 @@ struct virtio_pci_device { struct virtio_device vdev; struct pci_dev *pci_dev; + /* In legacy mode, these two point to within -legacy. */ + /* Where to read and clear interrupt */ + u8 __iomem *isr; + + /* Modern only fields */ + /* The IO mapping for the PCI config space (non-legacy mode) */ + struct virtio_pci_common_cfg __iomem *common; + /* Device-specific data (non-legacy mode) */ + void __iomem *device; + + /* So we can sanity-check accesses. */ + size_t device_len; + + /* Capability for when we need to map notifications per-vq. */ + int notify_map_cap; + + /* Multiply queue_notify_off by this value. (non-legacy mode). */ + u32 notify_offset_multiplier; + + /* Legacy only field */ /* the IO mapping for the PCI config space */ void __iomem *ioaddr; - /* the IO mapping for ISR operation */ - void __iomem *isr; - /* a list of queues so we can dispatch IRQs */ spinlock_t lock; struct list_head virtqueues; @@ -129,5 +146,7 @@ int vp_set_vq_affinity(struct virtqueue *vq, int cpu); int virtio_pci_legacy_probe(struct virtio_pci_device *); void virtio_pci_legacy_remove(struct virtio_pci_device *); +int virtio_pci_modern_probe(struct virtio_pci_device *); +void virtio_pci_modern_remove(struct virtio_pci_device *); #endif diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index 457cbe2..20c7638 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c @@ -505,6 +505,10 @@ static int virtio_pci_probe(struct pci_dev *pci_dev, if (rc) goto err_request_regions; + rc = virtio_pci_modern_probe(vp_dev); + if (rc != -ENODEV) + return rc; + rc = virtio_pci_legacy_probe(vp_dev); if (rc) goto err_probe; @@ -518,7 +522,10 @@ static int virtio_pci_probe(struct pci_dev *pci_dev, return 0; err_register: - virtio_pci_legacy_remove(vp_dev); + if (vp_dev-ioaddr) +virtio_pci_legacy_remove(vp_dev); + else +virtio_pci_modern_remove(vp_dev); err_probe: pci_release_regions(pci_dev); err_request_regions: @@ -534,7 +541,10 @@ static void virtio_pci_remove(struct pci_dev *pci_dev) unregister_virtio_device(vp_dev-vdev); - virtio_pci_legacy_remove(pci_dev); + if (vp_dev-ioaddr) + virtio_pci_legacy_remove(vp_dev); + else + virtio_pci_modern_remove(vp_dev); pci_release_regions(pci_dev); pci_disable_device(pci_dev); diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c new file mode 100644 index 000..38c0a11 --- /dev/null +++ b/drivers/virtio/virtio_pci_modern.c @@ -0,0 +1,592 @@ +/* + * Virtio PCI driver - legacy device support + * + * This module allows virtio devices to be used over a virtual PCI device. + * This can be used with QEMU based VMMs like KVM or Xen. + * + * Copyright IBM Corp. 2007 + * Copyright Red Hat, Inc. 2014 + * + * Authors: + * Anthony Liguori aligu...@us.ibm.com + * Rusty Russell ru...@rustcorp.com.au + * Michael S. Tsirkin m...@redhat.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#define VIRTIO_PCI_NO_LEGACY +#include virtio_pci_common.h + +static void __iomem *map_capability(struct pci_dev *dev, int off, + size_t minlen, + u32 align, + u32 start, u32 size, + size_t *len) +{ + u8 type_and_bar, bar; + u32 offset, length; + void __iomem *p; + + pci_read_config_byte(dev, off + offsetof(struct virtio_pci_cap, +type_and_bar), +type_and_bar); +
[PATCH v3 14/16] virtio_pci: macros for PCI layout offsets
From: Rusty Russell ru...@rustcorp.com.au QEMU wants it, so why not? Trust, but verify. Signed-off-by: Rusty Russell ru...@rustcorp.com.au Signed-off-by: Michael S. Tsirkin m...@redhat.com --- include/uapi/linux/virtio_pci.h| 30 drivers/virtio/virtio_pci_modern.c | 58 +- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h index 4e05423..e841edd 100644 --- a/include/uapi/linux/virtio_pci.h +++ b/include/uapi/linux/virtio_pci.h @@ -159,6 +159,36 @@ struct virtio_pci_common_cfg { __le32 queue_used_hi; /* read-write */ }; +/* Macro versions of offsets for the Old Timers! */ +#define VIRTIO_PCI_CAP_VNDR0 +#define VIRTIO_PCI_CAP_NEXT1 +#define VIRTIO_PCI_CAP_LEN 2 +#define VIRTIO_PCI_CAP_TYPE_AND_BAR3 +#define VIRTIO_PCI_CAP_OFFSET 4 +#define VIRTIO_PCI_CAP_LENGTH 8 + +#define VIRTIO_PCI_NOTIFY_CAP_MULT 12 + +#define VIRTIO_PCI_COMMON_DFSELECT 0 +#define VIRTIO_PCI_COMMON_DF 4 +#define VIRTIO_PCI_COMMON_GFSELECT 8 +#define VIRTIO_PCI_COMMON_GF 12 +#define VIRTIO_PCI_COMMON_MSIX 16 +#define VIRTIO_PCI_COMMON_NUMQ 18 +#define VIRTIO_PCI_COMMON_STATUS 20 +#define VIRTIO_PCI_COMMON_CFGGENERATION21 +#define VIRTIO_PCI_COMMON_Q_SELECT 22 +#define VIRTIO_PCI_COMMON_Q_SIZE 24 +#define VIRTIO_PCI_COMMON_Q_MSIX 26 +#define VIRTIO_PCI_COMMON_Q_ENABLE 28 +#define VIRTIO_PCI_COMMON_Q_NOFF 30 +#define VIRTIO_PCI_COMMON_Q_DESCLO 32 +#define VIRTIO_PCI_COMMON_Q_DESCHI 36 +#define VIRTIO_PCI_COMMON_Q_AVAILLO40 +#define VIRTIO_PCI_COMMON_Q_AVAILHI44 +#define VIRTIO_PCI_COMMON_Q_USEDLO 48 +#define VIRTIO_PCI_COMMON_Q_USEDHI 52 + #endif /* VIRTIO_PCI_NO_MODERN */ #endif diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index 38c0a11..5e0d309 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -469,9 +469,65 @@ static void virtio_pci_release_dev(struct device *_d) kfree(vp_dev); } -/* TODO: validate the ABI statically. */ +/* This is part of the ABI. Don't screw with it. */ static inline void check_offsets(void) { + /* Note: disk space was harmed in compilation of this function. */ + BUILD_BUG_ON(VIRTIO_PCI_CAP_VNDR != +offsetof(struct virtio_pci_cap, cap_vndr)); + BUILD_BUG_ON(VIRTIO_PCI_CAP_NEXT != +offsetof(struct virtio_pci_cap, cap_next)); + BUILD_BUG_ON(VIRTIO_PCI_CAP_LEN != +offsetof(struct virtio_pci_cap, cap_len)); + BUILD_BUG_ON(VIRTIO_PCI_CAP_TYPE_AND_BAR != +offsetof(struct virtio_pci_cap, type_and_bar)); + BUILD_BUG_ON(VIRTIO_PCI_CAP_OFFSET != +offsetof(struct virtio_pci_cap, offset)); + BUILD_BUG_ON(VIRTIO_PCI_CAP_LENGTH != +offsetof(struct virtio_pci_cap, length)); + BUILD_BUG_ON(VIRTIO_PCI_NOTIFY_CAP_MULT != +offsetof(struct virtio_pci_notify_cap, + notify_off_multiplier)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_DFSELECT != +offsetof(struct virtio_pci_common_cfg, + device_feature_select)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_DF != +offsetof(struct virtio_pci_common_cfg, device_feature)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_GFSELECT != +offsetof(struct virtio_pci_common_cfg, + guest_feature_select)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_GF != +offsetof(struct virtio_pci_common_cfg, guest_feature)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_MSIX != +offsetof(struct virtio_pci_common_cfg, msix_config)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_NUMQ != +offsetof(struct virtio_pci_common_cfg, num_queues)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_STATUS != +offsetof(struct virtio_pci_common_cfg, device_status)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_CFGGENERATION != +offsetof(struct virtio_pci_common_cfg, config_generation)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_SELECT != +offsetof(struct virtio_pci_common_cfg, queue_select)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_SIZE != +offsetof(struct virtio_pci_common_cfg, queue_size)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_MSIX != +offsetof(struct virtio_pci_common_cfg, queue_msix_vector)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_ENABLE != +offsetof(struct virtio_pci_common_cfg, queue_enable)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_NOFF != +offsetof(struct virtio_pci_common_cfg, queue_notify_off)); +
[PATCH v3 12/16] virtio-pci: define layout for virtio 1.0
From: Rusty Russell ru...@rustcorp.com.au Based on patches by Michael S. Tsirkin m...@redhat.com, but I found it hard to follow so changed to use structures which are more self-documenting. Signed-off-by: Rusty Russell ru...@rustcorp.com.au Signed-off-by: Michael S. Tsirkin m...@redhat.com --- include/uapi/linux/virtio_pci.h | 62 + 1 file changed, 62 insertions(+) diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h index 509d630..4e05423 100644 --- a/include/uapi/linux/virtio_pci.h +++ b/include/uapi/linux/virtio_pci.h @@ -99,4 +99,66 @@ /* Vector value used to disable MSI for queue */ #define VIRTIO_MSI_NO_VECTOR0x +#ifndef VIRTIO_PCI_NO_MODERN + +/* IDs for different capabilities. Must all exist. */ + +/* Common configuration */ +#define VIRTIO_PCI_CAP_COMMON_CFG 1 +/* Notifications */ +#define VIRTIO_PCI_CAP_NOTIFY_CFG 2 +/* ISR access */ +#define VIRTIO_PCI_CAP_ISR_CFG 3 +/* Device specific confiuration */ +#define VIRTIO_PCI_CAP_DEVICE_CFG 4 + +/* This is the PCI capability header: */ +struct virtio_pci_cap { + __u8 cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */ + __u8 cap_next; /* Generic PCI field: next ptr. */ + __u8 cap_len; /* Generic PCI field: capability length */ + __u8 type_and_bar; /* Upper 3 bits: bar. +* Lower 3 is VIRTIO_PCI_CAP_*_CFG. */ + __le32 offset; /* Offset within bar. */ + __le32 length; /* Length. */ +}; + +#define VIRTIO_PCI_CAP_BAR_SHIFT 5 +#define VIRTIO_PCI_CAP_BAR_MASK0x7 +#define VIRTIO_PCI_CAP_TYPE_SHIFT 0 +#define VIRTIO_PCI_CAP_TYPE_MASK 0x7 + +struct virtio_pci_notify_cap { + struct virtio_pci_cap cap; + __le32 notify_off_multiplier; /* Multiplier for queue_notify_off. */ +}; + +/* Fields in VIRTIO_PCI_CAP_COMMON_CFG: */ +struct virtio_pci_common_cfg { + /* About the whole device. */ + __le32 device_feature_select; /* read-write */ + __le32 device_feature; /* read-only */ + __le32 guest_feature_select;/* read-write */ + __le32 guest_feature; /* read-write */ + __le16 msix_config; /* read-write */ + __le16 num_queues; /* read-only */ + __u8 device_status; /* read-write */ + __u8 config_generation; /* read-only */ + + /* About a specific virtqueue. */ + __le16 queue_select;/* read-write */ + __le16 queue_size; /* read-write, power of 2. */ + __le16 queue_msix_vector; /* read-write */ + __le16 queue_enable;/* read-write */ + __le16 queue_notify_off;/* read-only */ + __le32 queue_desc_lo; /* read-write */ + __le32 queue_desc_hi; /* read-write */ + __le32 queue_avail_lo; /* read-write */ + __le32 queue_avail_hi; /* read-write */ + __le32 queue_used_lo; /* read-write */ + __le32 queue_used_hi; /* read-write */ +}; + +#endif /* VIRTIO_PCI_NO_MODERN */ + #endif -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v3 00/16] virtio-pci: towards virtio 1.0 guest support
Changes since v2: handling for devices without config space (e.g. rng) reduce # of mappings for VQs These patches seem to work fine on my virtio-1.0 qemu branch. There haven't been any bugs since v2: just minor cleanups and enhancements. QEMU side is still undergoing polishing, but is already testable. Rusty, what do you think? Let's merge these for 3.20? Also - will you be doing that merge window, or should I? Michael S. Tsirkin (14): virtio_pci: drop virtio_config dependency virtio/9p: verify device has config space virtio/blk: verify device has config space virtio/console: verify device has config space virtio/net: verify device has config space virtio/scsi: verify device has config space virtio/balloon: verify device has config space mn10300: drop dead code pci: add pci_iomap_range s390: add pci_iomap_range virtio_pci: move probe/remove code to common virtio_pci: modern driver virtio_pci_modern: reduce number of mappings virtio_pci_modern: support devices with no config Rusty Russell (2): virtio-pci: define layout for virtio 1.0 virtio_pci: macros for PCI layout offsets arch/s390/include/asm/pci_io.h| 1 + drivers/virtio/virtio_pci_common.h| 33 +- include/asm-generic/pci_iomap.h | 10 + include/uapi/linux/virtio_pci.h | 94 - arch/mn10300/unit-asb2305/pci-iomap.c | 35 -- arch/s390/pci/pci.c | 34 +- drivers/block/virtio_blk.c| 6 + drivers/char/virtio_console.c | 6 + drivers/net/virtio_net.c | 6 + drivers/scsi/virtio_scsi.c| 6 + drivers/virtio/virtio_balloon.c | 6 + drivers/virtio/virtio_pci_common.c| 79 +++- drivers/virtio/virtio_pci_legacy.c| 76 +--- drivers/virtio/virtio_pci_modern.c| 706 ++ lib/pci_iomap.c | 35 +- net/9p/trans_virtio.c | 6 + drivers/virtio/Makefile | 2 +- 17 files changed, 1016 insertions(+), 125 deletions(-) delete mode 100644 arch/mn10300/unit-asb2305/pci-iomap.c create mode 100644 drivers/virtio/virtio_pci_modern.c -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v3 01/16] virtio_pci: drop virtio_config dependency
virtio_pci does not depend on virtio_config: let's not include it, users can pull it in as necessary. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- include/uapi/linux/virtio_pci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h index 35b552c..509d630 100644 --- a/include/uapi/linux/virtio_pci.h +++ b/include/uapi/linux/virtio_pci.h @@ -39,7 +39,7 @@ #ifndef _LINUX_VIRTIO_PCI_H #define _LINUX_VIRTIO_PCI_H -#include linux/virtio_config.h +#include linux/types.h #ifndef VIRTIO_PCI_NO_LEGACY -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v3 15/16] virtio_pci_modern: reduce number of mappings
We don't know the # of VQs that drivers are going to use so it's hard to predict how much memory we'll need to map. However, the relevant capability does give us an upper limit. If that's below a page, we can reduce the number of required mappings by mapping it all once ahead of the time. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/virtio/virtio_pci_common.h | 3 ++ drivers/virtio/virtio_pci_modern.c | 57 -- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h index 610c43f..d391805 100644 --- a/drivers/virtio/virtio_pci_common.h +++ b/drivers/virtio/virtio_pci_common.h @@ -62,8 +62,11 @@ struct virtio_pci_device { struct virtio_pci_common_cfg __iomem *common; /* Device-specific data (non-legacy mode) */ void __iomem *device; + /* Base of vq notifications (non-legacy mode). */ + void __iomem *notify_base; /* So we can sanity-check accesses. */ + size_t notify_len; size_t device_len; /* Capability for when we need to map notifications per-vq. */ diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index 5e0d309..9c000e9a 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -333,10 +333,26 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, iowrite64_twopart(virt_to_phys(virtqueue_get_used(vq)), cfg-queue_used_lo, cfg-queue_used_hi); - vq-priv = (void __force *)map_capability(vp_dev-pci_dev, - vp_dev-notify_map_cap, 2, 2, - off * vp_dev-notify_offset_multiplier, 2, - NULL); + if (vp_dev-notify_base) { + /* offset should not wrap */ + if ((u64)off * vp_dev-notify_offset_multiplier + 2 +vp_dev-notify_len) { + dev_warn(vp_dev-pci_dev-dev, +bad notification offset %u (x %u) +for queue %u %zd, +off, vp_dev-notify_offset_multiplier, +index, vp_dev-notify_len); + err = -EINVAL; + goto err_map_notify; + } + vq-priv = (void __force *)vp_dev-notify_base + + off * vp_dev-notify_offset_multiplier; + } else { + vq-priv = (void __force *)map_capability(vp_dev-pci_dev, + vp_dev-notify_map_cap, 2, 2, + off * vp_dev-notify_offset_multiplier, 2, + NULL); + } if (!vq-priv) { err = -ENOMEM; @@ -355,7 +371,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, return vq; err_assign_vector: - pci_iounmap(vp_dev-pci_dev, (void __iomem __force *)vq-priv); + if (!vp_dev-notify_base) + pci_iounmap(vp_dev-pci_dev, (void __iomem __force *)vq-priv); err_map_notify: vring_del_virtqueue(vq); err_new_queue: @@ -400,7 +417,8 @@ static void del_vq(struct virtio_pci_vq_info *info) ioread16(vp_dev-common-queue_msix_vector); } - pci_iounmap(vp_dev-pci_dev, (void __force __iomem *)vq-priv); + if (!vp_dev-notify_base) + pci_iounmap(vp_dev-pci_dev, (void __force __iomem *)vq-priv); vring_del_virtqueue(vq); @@ -536,6 +554,7 @@ int virtio_pci_modern_probe(struct virtio_pci_device *vp_dev) struct pci_dev *pci_dev = vp_dev-pci_dev; int err, common, isr, notify, device; u32 notify_length; + u32 notify_offset; check_offsets(); @@ -602,13 +621,30 @@ int virtio_pci_modern_probe(struct virtio_pci_device *vp_dev) notify + offsetof(struct virtio_pci_notify_cap, notify_off_multiplier), vp_dev-notify_offset_multiplier); - /* Read notify length from config space. */ + /* Read notify length and offset from config space. */ pci_read_config_dword(pci_dev, notify + offsetof(struct virtio_pci_notify_cap, cap.length), notify_length); - vp_dev-notify_map_cap = notify; + pci_read_config_dword(pci_dev, + notify + offsetof(struct virtio_pci_notify_cap, + cap.length), + notify_offset); + + /* We don't know how many VQs we'll map, ahead of the time. +* If notify length is small, map it all now. +* Otherwise, map each VQ individually
[PATCH v3 16/16] virtio_pci_modern: support devices with no config
Virtio 1.0 spec lists device config as optional. Set get/set callbacks to NULL. Drivers can check that and fail gracefully. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/virtio/virtio_pci_modern.c | 21 +++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index 9c000e9a..b877705 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -425,6 +425,21 @@ static void del_vq(struct virtio_pci_vq_info *info) free_pages_exact(info-queue, vring_pci_size(info-num)); } +static const struct virtio_config_ops virtio_pci_config_nodev_ops = { + .get= NULL, + .set= NULL, + .generation = vp_generation, + .get_status = vp_get_status, + .set_status = vp_set_status, + .reset = vp_reset, + .find_vqs = vp_modern_find_vqs, + .del_vqs= vp_del_vqs, + .get_features = vp_get_features, + .finalize_features = vp_finalize_features, + .bus_name = vp_bus_name, + .set_vq_affinity = vp_set_vq_affinity, +}; + static const struct virtio_config_ops virtio_pci_config_ops = { .get= vp_get, .set= vp_set, @@ -655,9 +670,11 @@ int virtio_pci_modern_probe(struct virtio_pci_device *vp_dev) vp_dev-device_len); if (!vp_dev-device) goto err_map_device; - } - vp_dev-vdev.config = virtio_pci_config_ops; + vp_dev-vdev.config = virtio_pci_config_ops; + } else { + vp_dev-vdev.config = virtio_pci_config_nodev_ops; + } vp_dev-config_vector = vp_config_vector; vp_dev-setup_vq = setup_vq; -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PULL] uaccess: fix sparse warning on get/put_user for bitwise types
Hello, Arnd, As you asked, here's a pull request. This has been in linux-next apparently with no ill effects. The following changes since commit 99975cc6ada0d5f2675e83abecae05aba5f437d2: vhost/net: length miscalculation (2015-01-07 12:22:00 +0200) are available in the git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git tags/uaccess_for_upstream for you to fetch changes up to 0795cb1b46e7938ed679ccd48f933e75272b30e3: sparc32: nocheck uaccess coding style tweaks (2015-01-13 15:24:14 +0200) uaccess: fix sparse warning on get/put_user for bitwise types At the moment, if p and x are both tagged as bitwise types, some of get_user(x, p), put_user(x, p), __get_user(x, p), __put_user(x, p) might produce a sparse warning on many architectures. This is a false positive: *p on these architectures is loaded into long (typically using asm), then cast back to typeof(*p). When typeof(*p) is a bitwise type (which is uncommon), such a cast needs __force, otherwise sparse produces a warning. Some architectures already have the __force tag, add it where it's missing. I verified that adding these __force casts does not supress any useful warnings. Specifically, vhost wants to read/write bitwise types in userspace memory using get_user/put_user. At the moment this triggers sparse errors, since the value is passed through an integer. For example: __le32 __user *p; __u32 x; both put_user(x, p); and get_user(x, p); should be safe, but produce warnings on some architectures. While there, I noticed that a bunch of architectures violated coding style rules within uaccess macros. Included patches to fix them up. Signed-off-by: Michael S. Tsirkin m...@redhat.com Michael S. Tsirkin (37): x86/uaccess: fix sparse errors alpha/uaccess: fix sparse errors arm64/uaccess: fix sparse errors avr32/uaccess: fix sparse errors blackfin/uaccess: fix sparse errors cris/uaccess: fix sparse errors ia64/uaccess: fix sparse errors m32r/uaccess: fix sparse errors metag/uaccess: fix sparse errors openrisc/uaccess: fix sparse errors parisc/uaccess: fix sparse errors sh/uaccess: fix sparse errors sparc32/uaccess: fix sparse errors sparc64/uaccess: fix sparse errors m68k/uaccess: fix sparse errors arm: fix put_user sparse errors blackfin: fix put_user sparse errors ia64: fix put_user sparse errors metag: fix put_user sparse errors sh: fix put_user sparse errors avr32: whitespace fix sparc32: uaccess_32 macro whitespace fixes sparc64: uaccess_64 macro whitespace fixes blackfin: macro whitespace fixes alpha: macro whitespace fixes arm: macro whitespace fixes arm64: macro whitespace fixes avr32: macro whitespace fixes cris: macro whitespace fixes frv: macro whitespace fixes m32r: macro whitespace fixes m68k: macro whitespace fixes parisc: macro whitespace fixes sh: macro whitespace fixes xtensa: macro whitespace fixes sparc64: nocheck uaccess coding style tweaks sparc32: nocheck uaccess coding style tweaks arch/alpha/include/asm/uaccess.h| 86 - arch/arm/include/asm/uaccess.h | 96 +- arch/arm64/include/asm/uaccess.h| 4 +- arch/avr32/include/asm/uaccess.h| 24 +-- arch/blackfin/include/asm/uaccess.h | 32 ++-- arch/cris/include/asm/uaccess.h | 117 +++-- arch/frv/include/asm/segment.h | 2 +- arch/ia64/include/asm/uaccess.h | 11 +- arch/m32r/include/asm/uaccess.h | 88 +- arch/m68k/include/asm/segment.h | 2 +- arch/m68k/include/asm/uaccess_mm.h | 40 ++--- arch/metag/include/asm/uaccess.h| 25 +-- arch/openrisc/include/asm/uaccess.h | 4 +- arch/parisc/include/asm/uaccess.h | 116 ++-- arch/sh/include/asm/segment.h | 2 +- arch/sh/include/asm/uaccess.h | 4 +- arch/sh/include/asm/uaccess_64.h| 8 +- arch/sparc/include/asm/uaccess_32.h | 339 +--- arch/sparc/include/asm/uaccess_64.h | 222 --- arch/x86/include/asm/uaccess.h | 2 +- arch/xtensa/include/asm/uaccess.h | 90 +- 21 files changed, 700 insertions(+), 614 deletions(-) ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v3 08/16] mn10300: drop dead code
pci-iomap.c was (apparently, mistakenly) reintroduced as part of commit 83c2dc15ce824450e7044b9f90cd529c25747ae0 MN10300: Handle cacheable PCI regions in pci_iomap() probably as side-effect of forward-porting the patch from an old kernel. It's not really needed: the generic pci_iomap does the right thing here. The new file isn't compiled so it's safe to drop. Cc: Bjorn Helgaas bhelg...@google.com Cc: linux-...@vger.kernel.org Cc: triv...@kernel.org Cc: David Howells dhowe...@redhat.com Signed-off-by: Michael S. Tsirkin m...@redhat.com --- Can relevant people please ack this for merging through virtio tree? arch/mn10300/unit-asb2305/pci-iomap.c | 35 --- 1 file changed, 35 deletions(-) delete mode 100644 arch/mn10300/unit-asb2305/pci-iomap.c diff --git a/arch/mn10300/unit-asb2305/pci-iomap.c b/arch/mn10300/unit-asb2305/pci-iomap.c deleted file mode 100644 index bd65dae..000 --- a/arch/mn10300/unit-asb2305/pci-iomap.c +++ /dev/null @@ -1,35 +0,0 @@ -/* ASB2305 PCI I/O mapping handler - * - * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowe...@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public Licence - * as published by the Free Software Foundation; either version - * 2 of the Licence, or (at your option) any later version. - */ -#include linux/pci.h -#include linux/module.h - -/* - * Create a virtual mapping cookie for a PCI BAR (memory or IO) - */ -void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) -{ - resource_size_t start = pci_resource_start(dev, bar); - resource_size_t len = pci_resource_len(dev, bar); - unsigned long flags = pci_resource_flags(dev, bar); - - if (!len || !start) - return NULL; - - if ((flags IORESOURCE_IO) || (flags IORESOURCE_MEM)) { - if (flags IORESOURCE_CACHEABLE !(flags IORESOURCE_IO)) - return ioremap(start, len); - else - return ioremap_nocache(start, len); - } - - return NULL; -} -EXPORT_SYMBOL(pci_iomap); -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v3 07/16] virtio/balloon: verify device has config space
Some devices might not implement config space access (e.g. remoteproc used not to - before 3.9). virtio/balloon needs config space access so make it fail gracefully if not there. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/virtio/virtio_balloon.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 50c5f42..3176ea4 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -466,6 +466,12 @@ static int virtballoon_probe(struct virtio_device *vdev) struct virtio_balloon *vb; int err; + if (!vdev-config-get) { + dev_err(vdev-dev, %s failure: config access disabled\n, + __func__); + return -EINVAL; + } + vdev-priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL); if (!vb) { err = -ENOMEM; -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v3 09/16] pci: add pci_iomap_range
Virtio drivers should map the part of the BAR they need, not necessarily all of it. Cc: Bjorn Helgaas bhelg...@google.com Cc: linux-...@vger.kernel.org Acked-by: Arnd Bergmann a...@arndb.de Signed-off-by: Michael S. Tsirkin m...@redhat.com Signed-off-by: Rusty Russell ru...@rustcorp.com.au --- Bjorn, can you please ack this for merging through the virtio tree? include/asm-generic/pci_iomap.h | 10 ++ lib/pci_iomap.c | 35 ++- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/include/asm-generic/pci_iomap.h b/include/asm-generic/pci_iomap.h index ce37349..7389c87 100644 --- a/include/asm-generic/pci_iomap.h +++ b/include/asm-generic/pci_iomap.h @@ -15,6 +15,9 @@ struct pci_dev; #ifdef CONFIG_PCI /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); +extern void __iomem *pci_iomap_range(struct pci_dev *dev, int bar, +unsigned long offset, +unsigned long maxlen); /* Create a virtual mapping cookie for a port on a given PCI device. * Do not call this directly, it exists to make it easier for architectures * to override */ @@ -30,6 +33,13 @@ static inline void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned lon { return NULL; } + +static inline void __iomem *pci_iomap_range(struct pci_dev *dev, int bar, + unsigned long offset, + unsigned long maxlen) +{ + return NULL; +} #endif #endif /* __ASM_GENERIC_IO_H */ diff --git a/lib/pci_iomap.c b/lib/pci_iomap.c index 0d83ea8..bcce5f1 100644 --- a/lib/pci_iomap.c +++ b/lib/pci_iomap.c @@ -10,10 +10,11 @@ #ifdef CONFIG_PCI /** - * pci_iomap - create a virtual mapping cookie for a PCI BAR + * pci_iomap_range - create a virtual mapping cookie for a PCI BAR * @dev: PCI device that owns the BAR * @bar: BAR number - * @maxlen: length of the memory to map + * @offset: map memory at the given offset in BAR + * @maxlen: max length of the memory to map * * Using this function you will get a __iomem address to your device BAR. * You can access it using ioread*() and iowrite*(). These functions hide @@ -21,16 +22,21 @@ * you expect from them in the correct way. * * @maxlen specifies the maximum length to map. If you want to get access to - * the complete BAR without checking for its length first, pass %0 here. + * the complete BAR from offset to the end, pass %0 here. * */ -void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) +void __iomem *pci_iomap_range(struct pci_dev *dev, + int bar, + unsigned long offset, + unsigned long maxlen) { resource_size_t start = pci_resource_start(dev, bar); resource_size_t len = pci_resource_len(dev, bar); unsigned long flags = pci_resource_flags(dev, bar); - if (!len || !start) + if (len = offset || !start) return NULL; + len -= offset; + start += offset; if (maxlen len maxlen) len = maxlen; if (flags IORESOURCE_IO) @@ -43,6 +49,25 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) /* What? */ return NULL; } +EXPORT_SYMBOL(pci_iomap_range); +/** + * pci_iomap - create a virtual mapping cookie for a PCI BAR + * @dev: PCI device that owns the BAR + * @bar: BAR number + * @maxlen: length of the memory to map + * + * Using this function you will get a __iomem address to your device BAR. + * You can access it using ioread*() and iowrite*(). These functions hide + * the details if this is a MMIO or PIO address space and will just do what + * you expect from them in the correct way. + * + * @maxlen specifies the maximum length to map. If you want to get access to + * the complete BAR without checking for its length first, pass %0 here. + * */ +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) +{ + return pci_iomap_range(dev, bar, 0, maxlen); +} EXPORT_SYMBOL(pci_iomap); #endif /* CONFIG_PCI */ -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v3 11/16] virtio_pci: move probe/remove code to common
Most of initialization is device-independent. Let's move it to common. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/virtio/virtio_pci_common.h | 5 +-- drivers/virtio/virtio_pci_common.c | 69 +- drivers/virtio/virtio_pci_legacy.c | 76 -- 3 files changed, 77 insertions(+), 73 deletions(-) diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h index 5a49728..2b1e70d 100644 --- a/drivers/virtio/virtio_pci_common.h +++ b/drivers/virtio/virtio_pci_common.h @@ -127,8 +127,7 @@ const char *vp_bus_name(struct virtio_device *vdev); */ int vp_set_vq_affinity(struct virtqueue *vq, int cpu); -int virtio_pci_legacy_probe(struct pci_dev *pci_dev, - const struct pci_device_id *id); -void virtio_pci_legacy_remove(struct pci_dev *pci_dev); +int virtio_pci_legacy_probe(struct virtio_pci_device *); +void virtio_pci_legacy_remove(struct virtio_pci_device *); #endif diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index 9756f21..457cbe2 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c @@ -464,15 +464,80 @@ static const struct pci_device_id virtio_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, virtio_pci_id_table); +static void virtio_pci_release_dev(struct device *_d) +{ + struct virtio_device *vdev = dev_to_virtio(_d); + struct virtio_pci_device *vp_dev = to_vp_device(vdev); + + /* As struct device is a kobject, it's not safe to +* free the memory (including the reference counter itself) +* until it's release callback. */ + kfree(vp_dev); +} + static int virtio_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) { - return virtio_pci_legacy_probe(pci_dev, id); + struct virtio_pci_device *vp_dev; + int rc; + + /* allocate our structure and fill it out */ + vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL); + if (!vp_dev) + return -ENOMEM; + + pci_set_drvdata(pci_dev, vp_dev); + vp_dev-vdev.dev.parent = pci_dev-dev; + vp_dev-vdev.dev.release = virtio_pci_release_dev; + vp_dev-pci_dev = pci_dev; + INIT_LIST_HEAD(vp_dev-virtqueues); + spin_lock_init(vp_dev-lock); + + /* Disable MSI/MSIX to bring device to a known good state. */ + pci_msi_off(pci_dev); + + /* enable the device */ + rc = pci_enable_device(pci_dev); + if (rc) + goto err_enable_device; + + rc = pci_request_regions(pci_dev, virtio-pci); + if (rc) + goto err_request_regions; + + rc = virtio_pci_legacy_probe(vp_dev); + if (rc) + goto err_probe; + + pci_set_master(pci_dev); + + rc = register_virtio_device(vp_dev-vdev); + if (rc) + goto err_register; + + return 0; + +err_register: + virtio_pci_legacy_remove(vp_dev); +err_probe: + pci_release_regions(pci_dev); +err_request_regions: + pci_disable_device(pci_dev); +err_enable_device: + kfree(vp_dev); + return rc; } static void virtio_pci_remove(struct pci_dev *pci_dev) { - virtio_pci_legacy_remove(pci_dev); + struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); + + unregister_virtio_device(vp_dev-vdev); + + virtio_pci_legacy_remove(pci_dev); + + pci_release_regions(pci_dev); + pci_disable_device(pci_dev); } static struct pci_driver virtio_pci_driver = { diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c index a5486e6..256a527 100644 --- a/drivers/virtio/virtio_pci_legacy.c +++ b/drivers/virtio/virtio_pci_legacy.c @@ -211,23 +211,10 @@ static const struct virtio_config_ops virtio_pci_config_ops = { .set_vq_affinity = vp_set_vq_affinity, }; -static void virtio_pci_release_dev(struct device *_d) -{ - struct virtio_device *vdev = dev_to_virtio(_d); - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - - /* As struct device is a kobject, it's not safe to -* free the memory (including the reference counter itself) -* until it's release callback. */ - kfree(vp_dev); -} - /* the PCI probing function */ -int virtio_pci_legacy_probe(struct pci_dev *pci_dev, - const struct pci_device_id *id) +int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev) { - struct virtio_pci_device *vp_dev; - int err; + struct pci_dev *pci_dev = vp_dev-pci_dev; /* We only own devices = 0x1000 and = 0x103f: leave the rest. */ if (pci_dev-device 0x1000 || pci_dev-device 0x103f) @@ -239,41 +226,12 @@ int virtio_pci_legacy_probe(struct pci_dev *pci_dev, return -ENODEV; } - /* allocate our structure and fill it out */ - vp_dev =
[PATCH v3 10/16] s390: add pci_iomap_range
Virtio drivers should map the part of the range they need, not necessarily all of it. To this end, support mapping ranges within BAR on s390. Since multiple ranges can now be mapped within a BAR, we keep track of the number of mappings created, and only clear out the mapping for a BAR when this number reaches 0. Cc: Bjorn Helgaas bhelg...@google.com Cc: linux-...@vger.kernel.org Tested-by: Sebastian Ott seb...@linux.vnet.ibm.com Signed-off-by: Michael S. Tsirkin m...@redhat.com --- Heiko, Martin, can you please ack merging this through the virtio tree? This was lightly tested by Sebastian Ott. arch/s390/include/asm/pci_io.h | 1 + arch/s390/pci/pci.c| 34 +++--- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h index f664e96..1a9a98d 100644 --- a/arch/s390/include/asm/pci_io.h +++ b/arch/s390/include/asm/pci_io.h @@ -16,6 +16,7 @@ struct zpci_iomap_entry { u32 fh; u8 bar; + u16 count; }; extern struct zpci_iomap_entry *zpci_iomap_start; diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 3290f11..753a567 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -259,7 +259,10 @@ void __iowrite64_copy(void __iomem *to, const void *from, size_t count) } /* Create a virtual mapping cookie for a PCI BAR */ -void __iomem *pci_iomap(struct pci_dev *pdev, int bar, unsigned long max) +void __iomem *pci_iomap_range(struct pci_dev *pdev, + int bar, + unsigned long offset, + unsigned long max) { struct zpci_dev *zdev = get_zdev(pdev); u64 addr; @@ -270,14 +273,27 @@ void __iomem *pci_iomap(struct pci_dev *pdev, int bar, unsigned long max) idx = zdev-bars[bar].map_idx; spin_lock(zpci_iomap_lock); - zpci_iomap_start[idx].fh = zdev-fh; - zpci_iomap_start[idx].bar = bar; + if (zpci_iomap_start[idx].count++) { + BUG_ON(zpci_iomap_start[idx].fh != zdev-fh || + zpci_iomap_start[idx].bar != bar); + } else { + zpci_iomap_start[idx].fh = zdev-fh; + zpci_iomap_start[idx].bar = bar; + } + /* Detect overrun */ + BUG_ON(!zpci_iomap_start[idx].count); spin_unlock(zpci_iomap_lock); addr = ZPCI_IOMAP_ADDR_BASE | ((u64) idx 48); - return (void __iomem *) addr; + return (void __iomem *) addr + offset; } -EXPORT_SYMBOL_GPL(pci_iomap); +EXPORT_SYMBOL_GPL(pci_iomap_range); + +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) +{ + return pci_iomap_range(dev, bar, 0, maxlen); +} +EXPORT_SYMBOL(pci_iomap); void pci_iounmap(struct pci_dev *pdev, void __iomem *addr) { @@ -285,8 +301,12 @@ void pci_iounmap(struct pci_dev *pdev, void __iomem *addr) idx = (((__force u64) addr) ~ZPCI_IOMAP_ADDR_BASE) 48; spin_lock(zpci_iomap_lock); - zpci_iomap_start[idx].fh = 0; - zpci_iomap_start[idx].bar = 0; + /* Detect underrun */ + BUG_ON(!zpci_iomap_start[idx].count); + if (!--zpci_iomap_start[idx].count) { + zpci_iomap_start[idx].fh = 0; + zpci_iomap_start[idx].bar = 0; + } spin_unlock(zpci_iomap_lock); } EXPORT_SYMBOL_GPL(pci_iounmap); -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v3 04/16] virtio/console: verify device has config space
Some devices might not implement config space access (e.g. remoteproc used not to - before 3.9). virtio/console needs config space access so make it fail gracefully if not there. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/char/virtio_console.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index de03df9..26afb56 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1986,6 +1986,12 @@ static int virtcons_probe(struct virtio_device *vdev) bool multiport; bool early = early_put_chars != NULL; + if (!vdev-config-get) { + dev_err(vdev-dev, %s failure: config access disabled\n, + __func__); + return -EINVAL; + } + /* Ensure to read early_put_chars now */ barrier(); -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v3 06/16] virtio/scsi: verify device has config space
Some devices might not implement config space access (e.g. remoteproc used not to - before 3.9). virtio/scsi needs config space access so make it fail gracefully if not there. Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/scsi/virtio_scsi.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index c52bb5d..f164f24 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -950,6 +950,12 @@ static int virtscsi_probe(struct virtio_device *vdev) u32 num_queues; struct scsi_host_template *hostt; + if (!vdev-config-get) { + dev_err(vdev-dev, %s failure: config access disabled\n, + __func__); + return -EINVAL; + } + /* We need to know how many queues before we allocate. */ num_queues = virtscsi_config_get(vdev, num_queues) ? : 1; -- MST ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization