Pull xen updates from Juergen Gross: - fix a bug introduced in 5.5 in the Xen gntdev driver - fix the Xen balloon driver when running on ancient Xen versions - allow Xen stubdoms to control interrupt enable flags of passed-through PCI cards - release resources in Xen backends under memory pressure * tag 'for-linus-5.6-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen/blkback: Consistently insert one empty line between functions xen/blkback: Remove unnecessary static variable name prefixes xen/blkback: Squeeze page pools if a memory pressure is detected xenbus/backend: Protect xenbus callback with lock xenbus/backend: Add memory pressure handler callback xen/gntdev: Do not use mm notifiers with autotranslating guests xen/balloon: Support xend-based toolstack take two xen-pciback: optionally allow interrupt enable flag writes
Unified · Split
| @@ -11,3 +11,16 @@ Description: · 10 unmodified lines | |||
| 11 | #echo 00:19.0-E0:2:FF > /sys/bus/pci/drivers/pciback/quirks | 11 | #echo 00:19.0-E0:2:FF > /sys/bus/pci/drivers/pciback/quirks |
| 12 | will allow the guest to read and write to the configuration | 12 | will allow the guest to read and write to the configuration |
| 13 | register 0x0E. | 13 | register 0x0E. |
| 14 | |||
| 15 | What: /sys/bus/pci/drivers/pciback/allow_interrupt_control | ||
| 16 | Date: Jan 2020 | ||
| 17 | KernelVersion: 5.6 | ||
| 18 | Contact: xen-devel@lists.xenproject.org | ||
| 19 | Description: | ||
| 20 | List of devices which can have interrupt control flag (INTx, | ||
| 21 | MSI, MSI-X) set by a connected guest. It is meant to be set | ||
| 22 | only when the guest is a stubdomain hosting device model (qemu) | ||
| 23 | and the actual device is assigned to a HVM. It is not safe | ||
| 24 | (similar to permissive attribute) to set for a devices assigned | ||
| 25 | to a PV guest. The device is automatically removed from this | ||
| 26 | list when the connected pcifront terminates. | ||
| @@ -25,3 +25,13 @@ Description: · 24 unmodified lines | |||
| 25 | allocated without being in use. The time is in | 25 | allocated without being in use. The time is in |
| 26 | seconds, 0 means indefinitely long. | 26 | seconds, 0 means indefinitely long. |
| 27 | The default is 60 seconds. | 27 | The default is 60 seconds. |
| 28 | |||
| 29 | What: /sys/module/xen_blkback/parameters/buffer_squeeze_duration_ms | ||
| 30 | Date: December 2019 | ||
| 31 | KernelVersion: 5.6 | ||
| 32 | Contact: SeongJae Park <sjpark@amazon.de> | ||
| 33 | Description: | ||
| 34 | When memory pressure is reported to blkback this option | ||
| 35 | controls the duration in milliseconds that blkback will not | ||
| 36 | cache any page not backed by a grant mapping. | ||
| 37 | The default is 10ms. | ||
| @@ -62,8 +62,8 @@ · 61 unmodified lines | |||
| 62 | * IO workloads. | 62 | * IO workloads. |
| 63 | */ | 63 | */ |
| 64 | 64 | ||
| 65 | static int xen_blkif_max_buffer_pages = 1024; | 65 | static int max_buffer_pages = 1024; |
| 66 | module_param_named(max_buffer_pages, xen_blkif_max_buffer_pages, int, 0644); | 66 | module_param_named(max_buffer_pages, max_buffer_pages, int, 0644); |
| 67 | MODULE_PARM_DESC(max_buffer_pages, | 67 | MODULE_PARM_DESC(max_buffer_pages, |
| 68 | "Maximum number of free pages to keep in each block backend buffer"); | 68 | "Maximum number of free pages to keep in each block backend buffer"); |
| 69 | 69 | ||
| @@ -78,8 +78,8 @@ MODULE_PARM_DESC(max_buffer_pages, · 8 unmodified lines | |||
| 78 | * algorithm. | 78 | * algorithm. |
| 79 | */ | 79 | */ |
| 80 | 80 | ||
| 81 | static int xen_blkif_max_pgrants = 1056; | 81 | static int max_pgrants = 1056; |
| 82 | module_param_named(max_persistent_grants, xen_blkif_max_pgrants, int, 0644); | 82 | module_param_named(max_persistent_grants, max_pgrants, int, 0644); |
| 83 | MODULE_PARM_DESC(max_persistent_grants, | 83 | MODULE_PARM_DESC(max_persistent_grants, |
| 84 | "Maximum number of grants to map persistently"); | 84 | "Maximum number of grants to map persistently"); |
| 85 | 85 | ||
| @@ -88,8 +88,8 @@ MODULE_PARM_DESC(max_persistent_grants, · 2 unmodified lines | |||
| 88 | * use. The time is in seconds, 0 means indefinitely long. | 88 | * use. The time is in seconds, 0 means indefinitely long. |
| 89 | */ | 89 | */ |
| 90 | 90 | ||
| 91 | static unsigned int xen_blkif_pgrant_timeout = 60; | 91 | static unsigned int pgrant_timeout = 60; |
| 92 | module_param_named(persistent_grant_unused_seconds, xen_blkif_pgrant_timeout, | 92 | module_param_named(persistent_grant_unused_seconds, pgrant_timeout, |
| 93 | uint, 0644); | 93 | uint, 0644); |
| 94 | MODULE_PARM_DESC(persistent_grant_unused_seconds, | 94 | MODULE_PARM_DESC(persistent_grant_unused_seconds, |
| 95 | "Time in seconds an unused persistent grant is allowed to " | 95 | "Time in seconds an unused persistent grant is allowed to " |
| @@ -137,9 +137,8 @@ module_param(log_stats, int, 0644); · 41 unmodified lines | |||
| 137 | 137 | ||
| 138 | static inline bool persistent_gnt_timeout(struct persistent_gnt *persistent_gnt) | 138 | static inline bool persistent_gnt_timeout(struct persistent_gnt *persistent_gnt) |
| 139 | { | 139 | { |
| 140 | return xen_blkif_pgrant_timeout && | 140 | return pgrant_timeout && (jiffies - persistent_gnt->last_used >= |
| 141 | (jiffies - persistent_gnt->last_used >= | 141 | HZ * pgrant_timeout); |
| 142 | HZ * xen_blkif_pgrant_timeout); | ||
| 143 | } | 142 | } |
| 144 | 143 | ||
| 145 | static inline int get_free_page(struct xen_blkif_ring *ring, struct page **page) | 144 | static inline int get_free_page(struct xen_blkif_ring *ring, struct page **page) |
| @@ -234,7 +233,7 @@ static int add_persistent_gnt(struct xen_blkif_ring *ring, · 88 unmodified lines | |||
| 234 | struct persistent_gnt *this; | 233 | struct persistent_gnt *this; |
| 235 | struct xen_blkif *blkif = ring->blkif; | 234 | struct xen_blkif *blkif = ring->blkif; |
| 236 | 235 | ||
| 237 | if (ring->persistent_gnt_c >= xen_blkif_max_pgrants) { | 236 | if (ring->persistent_gnt_c >= max_pgrants) { |
| 238 | if (!blkif->vbd.overflow_max_grants) | 237 | if (!blkif->vbd.overflow_max_grants) |
| 239 | blkif->vbd.overflow_max_grants = 1; | 238 | blkif->vbd.overflow_max_grants = 1; |
| 240 | return -EBUSY; | 239 | return -EBUSY; |
| @@ -397,14 +396,13 @@ static void purge_persistent_gnt(struct xen_blkif_ring *ring) · 156 unmodified lines | |||
| 397 | goto out; | 396 | goto out; |
| 398 | } | 397 | } |
| 399 | 398 | ||
| 400 | if (ring->persistent_gnt_c < xen_blkif_max_pgrants || | 399 | if (ring->persistent_gnt_c < max_pgrants || |
| 401 | (ring->persistent_gnt_c == xen_blkif_max_pgrants && | 400 | (ring->persistent_gnt_c == max_pgrants && |
| 402 | !ring->blkif->vbd.overflow_max_grants)) { | 401 | !ring->blkif->vbd.overflow_max_grants)) { |
| 403 | num_clean = 0; | 402 | num_clean = 0; |
| 404 | } else { | 403 | } else { |
| 405 | num_clean = (xen_blkif_max_pgrants / 100) * LRU_PERCENT_CLEAN; | 404 | num_clean = (max_pgrants / 100) * LRU_PERCENT_CLEAN; |
| 406 | num_clean = ring->persistent_gnt_c - xen_blkif_max_pgrants + | 405 | num_clean = ring->persistent_gnt_c - max_pgrants + num_clean; |
| 407 | num_clean; | ||
| 408 | num_clean = min(ring->persistent_gnt_c, num_clean); | 406 | num_clean = min(ring->persistent_gnt_c, num_clean); |
| 409 | pr_debug("Going to purge at least %u persistent grants\n", | 407 | pr_debug("Going to purge at least %u persistent grants\n", |
| 410 | num_clean); | 408 | num_clean); |
| @@ -599,8 +597,7 @@ static void print_stats(struct xen_blkif_ring *ring) · 188 unmodified lines | |||
| 599 | current->comm, ring->st_oo_req, | 597 | current->comm, ring->st_oo_req, |
| 600 | ring->st_rd_req, ring->st_wr_req, | 598 | ring->st_rd_req, ring->st_wr_req, |
| 601 | ring->st_f_req, ring->st_ds_req, | 599 | ring->st_f_req, ring->st_ds_req, |
| 602 | ring->persistent_gnt_c, | 600 | ring->persistent_gnt_c, max_pgrants); |
| 603 | xen_blkif_max_pgrants); | ||
| 604 | ring->st_print = jiffies + msecs_to_jiffies(10 * 1000); | 601 | ring->st_print = jiffies + msecs_to_jiffies(10 * 1000); |
| 605 | ring->st_rd_req = 0; | 602 | ring->st_rd_req = 0; |
| 606 | ring->st_wr_req = 0; | 603 | ring->st_wr_req = 0; |
| @@ -656,8 +653,11 @@ purge_gnt_list: · 49 unmodified lines | |||
| 656 | ring->next_lru = jiffies + msecs_to_jiffies(LRU_INTERVAL); | 653 | ring->next_lru = jiffies + msecs_to_jiffies(LRU_INTERVAL); |
| 657 | } | 654 | } |
| 658 | 655 | ||
| 659 | /* Shrink if we have more than xen_blkif_max_buffer_pages */ | 656 | /* Shrink the free pages pool if it is too large. */ |
| 660 | shrink_free_pagepool(ring, xen_blkif_max_buffer_pages); | 657 | if (time_before(jiffies, blkif->buffer_squeeze_end)) |
| 658 | shrink_free_pagepool(ring, 0); | ||
| 659 | else | ||
| 660 | shrink_free_pagepool(ring, max_buffer_pages); | ||
| 661 | 661 | ||
| 662 | if (log_stats && time_after(jiffies, ring->st_print)) | 662 | if (log_stats && time_after(jiffies, ring->st_print)) |
| 663 | print_stats(ring); | 663 | print_stats(ring); |
| @@ -884,7 +884,7 @@ again: · 220 unmodified lines | |||
| 884 | continue; | 884 | continue; |
| 885 | } | 885 | } |
| 886 | if (use_persistent_gnts && | 886 | if (use_persistent_gnts && |
| 887 | ring->persistent_gnt_c < xen_blkif_max_pgrants) { | 887 | ring->persistent_gnt_c < max_pgrants) { |
| 888 | /* | 888 | /* |
| 889 | * We are using persistent grants, the grant is | 889 | * We are using persistent grants, the grant is |
| 890 | * not mapped but we might have room for it. | 890 | * not mapped but we might have room for it. |
| @@ -911,7 +911,7 @@ again: · 20 unmodified lines | |||
| 911 | pages[seg_idx]->persistent_gnt = persistent_gnt; | 911 | pages[seg_idx]->persistent_gnt = persistent_gnt; |
| 912 | pr_debug("grant %u added to the tree of persistent grants, using %u/%u\n", | 912 | pr_debug("grant %u added to the tree of persistent grants, using %u/%u\n", |
| 913 | persistent_gnt->gnt, ring->persistent_gnt_c, | 913 | persistent_gnt->gnt, ring->persistent_gnt_c, |
| 914 | xen_blkif_max_pgrants); | 914 | max_pgrants); |
| 915 | goto next; | 915 | goto next; |
| 916 | } | 916 | } |
| 917 | if (use_persistent_gnts && !blkif->vbd.overflow_max_grants) { | 917 | if (use_persistent_gnts && !blkif->vbd.overflow_max_grants) { |
| @@ -319,6 +319,7 @@ struct xen_blkif { · 318 unmodified lines | |||
| 319 | /* All rings for this device. */ | 319 | /* All rings for this device. */ |
| 320 | struct xen_blkif_ring *rings; | 320 | struct xen_blkif_ring *rings; |
| 321 | unsigned int nr_rings; | 321 | unsigned int nr_rings; |
| 322 | unsigned long buffer_squeeze_end; | ||
| 322 | }; | 323 | }; |
| 323 | 324 | ||
| 324 | struct seg_buf { | 325 | struct seg_buf { |
| @@ -467,7 +467,6 @@ static void xenvbd_sysfs_delif(struct xenbus_device *dev) · 466 unmodified lines | |||
| 467 | device_remove_file(&dev->dev, &dev_attr_physical_device); | 467 | device_remove_file(&dev->dev, &dev_attr_physical_device); |
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | |||
| 471 | static void xen_vbd_free(struct xen_vbd *vbd) | 470 | static void xen_vbd_free(struct xen_vbd *vbd) |
| 472 | { | 471 | { |
| 473 | if (vbd->bdev) | 472 | if (vbd->bdev) |
| @@ -524,6 +523,7 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, · 50 unmodified lines | |||
| 524 | handle, blkif->domid); | 523 | handle, blkif->domid); |
| 525 | return 0; | 524 | return 0; |
| 526 | } | 525 | } |
| 526 | |||
| 527 | static int xen_blkbk_remove(struct xenbus_device *dev) | 527 | static int xen_blkbk_remove(struct xenbus_device *dev) |
| 528 | { | 528 | { |
| 529 | struct backend_info *be = dev_get_drvdata(&dev->dev); | 529 | struct backend_info *be = dev_get_drvdata(&dev->dev); |
| @@ -607,6 +607,7 @@ static void xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info · 77 unmodified lines | |||
| 607 | if (err) | 607 | if (err) |
| 608 | dev_warn(&dev->dev, "writing feature-discard (%d)", err); | 608 | dev_warn(&dev->dev, "writing feature-discard (%d)", err); |
| 609 | } | 609 | } |
| 610 | |||
| 610 | int xen_blkbk_barrier(struct xenbus_transaction xbt, | 611 | int xen_blkbk_barrier(struct xenbus_transaction xbt, |
| 611 | struct backend_info *be, int state) | 612 | struct backend_info *be, int state) |
| 612 | { | 613 | { |
| @@ -691,7 +692,6 @@ fail: · 78 unmodified lines | |||
| 691 | return err; | 692 | return err; |
| 692 | } | 693 | } |
| 693 | 694 | ||
| 694 | |||
| 695 | /* | 695 | /* |
| 696 | * Callback received when the hotplug scripts have placed the physical-device | 696 | * Callback received when the hotplug scripts have placed the physical-device |
| 697 | * node. Read it and the mode node, and create a vbd. If the frontend is | 697 | * node. Read it and the mode node, and create a vbd. If the frontend is |
| @@ -783,7 +783,6 @@ static void backend_changed(struct xenbus_watch *watch, · 85 unmodified lines | |||
| 783 | } | 783 | } |
| 784 | } | 784 | } |
| 785 | 785 | ||
| 786 | |||
| 787 | /* | 786 | /* |
| 788 | * Callback received when the frontend's state changes. | 787 | * Callback received when the frontend's state changes. |
| 789 | */ | 788 | */ |
| @@ -858,9 +857,27 @@ static void frontend_changed(struct xenbus_device *dev, · 68 unmodified lines | |||
| 858 | } | 857 | } |
| 859 | } | 858 | } |
| 860 | 859 | ||
| 860 | /* Once a memory pressure is detected, squeeze free page pools for a while. */ | ||
| 861 | static unsigned int buffer_squeeze_duration_ms = 10; | ||
| 862 | module_param_named(buffer_squeeze_duration_ms, | ||
| 863 | buffer_squeeze_duration_ms, int, 0644); | ||
| 864 | MODULE_PARM_DESC(buffer_squeeze_duration_ms, | ||
| 865 | "Duration in ms to squeeze pages buffer when a memory pressure is detected"); | ||
| 861 | 866 | ||
| 862 | /* ** Connection ** */ | 867 | /* |
| 868 | * Callback received when the memory pressure is detected. | ||
| 869 | */ | ||
| 870 | static void reclaim_memory(struct xenbus_device *dev) | ||
| 871 | { | ||
| 872 | struct backend_info *be = dev_get_drvdata(&dev->dev); | ||
| 863 | 873 | ||
| 874 | if (!be) | ||
| 875 | return; | ||
| 876 | be->blkif->buffer_squeeze_end = jiffies + | ||
| 877 | msecs_to_jiffies(buffer_squeeze_duration_ms); | ||
| 878 | } | ||
| 879 | |||
| 880 | /* ** Connection ** */ | ||
| 864 | 881 | ||
| 865 | /* | 882 | /* |
| 866 | * Write the physical details regarding the block device to the store, and | 883 | * Write the physical details regarding the block device to the store, and |
| @@ -1152,6 +1169,7 @@ static struct xenbus_driver xen_blkbk_driver = { · 285 unmodified lines | |||
| 1152 | .remove = xen_blkbk_remove, | 1169 | .remove = xen_blkbk_remove, |
| 1153 | .otherend_changed = frontend_changed, | 1170 | .otherend_changed = frontend_changed, |
| 1154 | .allow_rebind = true, | 1171 | .allow_rebind = true, |
| 1172 | .reclaim_memory = reclaim_memory, | ||
| 1155 | }; | 1173 | }; |
| 1156 | 1174 | ||
| 1157 | int xen_blkif_xenbus_init(void) | 1175 | int xen_blkif_xenbus_init(void) |
| @@ -1006,19 +1006,19 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) · 1005 unmodified lines | |||
| 1006 | } | 1006 | } |
| 1007 | mutex_unlock(&priv->lock); | 1007 | mutex_unlock(&priv->lock); |
| 1008 | 1008 | ||
| 1009 | /* | ||
| 1010 | * gntdev takes the address of the PTE in find_grant_ptes() and passes | ||
| 1011 | * it to the hypervisor in gntdev_map_grant_pages(). The purpose of | ||
| 1012 | * the notifier is to prevent the hypervisor pointer to the PTE from | ||
| 1013 | * going stale. | ||
| 1014 | * | ||
| 1015 | * Since this vma's mappings can't be touched without the mmap_sem, | ||
| 1016 | * and we are holding it now, there is no need for the notifier_range | ||
| 1017 | * locking pattern. | ||
| 1018 | */ | ||
| 1019 | mmu_interval_read_begin(&map->notifier); | ||
| 1020 | |||
| 1021 | if (use_ptemod) { | 1009 | if (use_ptemod) { |
| 1010 | /* | ||
| 1011 | * gntdev takes the address of the PTE in find_grant_ptes() and | ||
| 1012 | * passes it to the hypervisor in gntdev_map_grant_pages(). The | ||
| 1013 | * purpose of the notifier is to prevent the hypervisor pointer | ||
| 1014 | * to the PTE from going stale. | ||
| 1015 | * | ||
| 1016 | * Since this vma's mappings can't be touched without the | ||
| 1017 | * mmap_sem, and we are holding it now, there is no need for | ||
| 1018 | * the notifier_range locking pattern. | ||
| 1019 | */ | ||
| 1020 | mmu_interval_read_begin(&map->notifier); | ||
| 1021 | |||
| 1022 | map->pages_vm_start = vma->vm_start; | 1022 | map->pages_vm_start = vma->vm_start; |
| 1023 | err = apply_to_page_range(vma->vm_mm, vma->vm_start, | 1023 | err = apply_to_page_range(vma->vm_mm, vma->vm_start, |
| 1024 | vma->vm_end - vma->vm_start, | 1024 | vma->vm_end - vma->vm_start, |
| @@ -94,7 +94,7 @@ static void watch_target(struct xenbus_watch *watch, · 93 unmodified lines | |||
| 94 | "%llu", &static_max) == 1)) | 94 | "%llu", &static_max) == 1)) |
| 95 | static_max >>= PAGE_SHIFT - 10; | 95 | static_max >>= PAGE_SHIFT - 10; |
| 96 | else | 96 | else |
| 97 | static_max = new_target; | 97 | static_max = balloon_stats.current_pages; |
| 98 | 98 | ||
| 99 | target_diff = (xen_pv_domain() || xen_initial_domain()) ? 0 | 99 | target_diff = (xen_pv_domain() || xen_initial_domain()) ? 0 |
| 100 | : static_max - balloon_stats.target_pages; | 100 | : static_max - balloon_stats.target_pages; |
| @@ -286,6 +286,43 @@ int xen_pcibk_config_write(struct pci_dev *dev, int offset, int size, u32 value) · 285 unmodified lines | |||
| 286 | return xen_pcibios_err_to_errno(err); | 286 | return xen_pcibios_err_to_errno(err); |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | int xen_pcibk_get_interrupt_type(struct pci_dev *dev) | ||
| 290 | { | ||
| 291 | int err; | ||
| 292 | u16 val; | ||
| 293 | int ret = 0; | ||
| 294 | |||
| 295 | err = pci_read_config_word(dev, PCI_COMMAND, &val); | ||
| 296 | if (err) | ||
| 297 | return err; | ||
| 298 | if (!(val & PCI_COMMAND_INTX_DISABLE)) | ||
| 299 | ret |= INTERRUPT_TYPE_INTX; | ||
| 300 | |||
| 301 | /* | ||
| 302 | * Do not trust dev->msi(x)_enabled here, as enabling could be done | ||
| 303 | * bypassing the pci_*msi* functions, by the qemu. | ||
| 304 | */ | ||
| 305 | if (dev->msi_cap) { | ||
| 306 | err = pci_read_config_word(dev, | ||
| 307 | dev->msi_cap + PCI_MSI_FLAGS, | ||
| 308 | &val); | ||
| 309 | if (err) | ||
| 310 | return err; | ||
| 311 | if (val & PCI_MSI_FLAGS_ENABLE) | ||
| 312 | ret |= INTERRUPT_TYPE_MSI; | ||
| 313 | } | ||
| 314 | if (dev->msix_cap) { | ||
| 315 | err = pci_read_config_word(dev, | ||
| 316 | dev->msix_cap + PCI_MSIX_FLAGS, | ||
| 317 | &val); | ||
| 318 | if (err) | ||
| 319 | return err; | ||
| 320 | if (val & PCI_MSIX_FLAGS_ENABLE) | ||
| 321 | ret |= INTERRUPT_TYPE_MSIX; | ||
| 322 | } | ||
| 323 | return ret; | ||
| 324 | } | ||
| 325 | |||
| 289 | void xen_pcibk_config_free_dyn_fields(struct pci_dev *dev) | 326 | void xen_pcibk_config_free_dyn_fields(struct pci_dev *dev) |
| 290 | { | 327 | { |
| 291 | struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev); | 328 | struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev); |
| @@ -65,6 +65,11 @@ struct config_field_entry { · 64 unmodified lines | |||
| 65 | void *data; | 65 | void *data; |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | #define INTERRUPT_TYPE_NONE (1<<0) | ||
| 69 | #define INTERRUPT_TYPE_INTX (1<<1) | ||
| 70 | #define INTERRUPT_TYPE_MSI (1<<2) | ||
| 71 | #define INTERRUPT_TYPE_MSIX (1<<3) | ||
| 72 | |||
| 68 | extern bool xen_pcibk_permissive; | 73 | extern bool xen_pcibk_permissive; |
| 69 | 74 | ||
| 70 | #define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset) | 75 | #define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset) |
| @@ -126,4 +131,6 @@ int xen_pcibk_config_capability_init(void); · 55 unmodified lines | |||
| 126 | int xen_pcibk_config_header_add_fields(struct pci_dev *dev); | 131 | int xen_pcibk_config_header_add_fields(struct pci_dev *dev); |
| 127 | int xen_pcibk_config_capability_add_fields(struct pci_dev *dev); | 132 | int xen_pcibk_config_capability_add_fields(struct pci_dev *dev); |
| 128 | 133 | ||
| 134 | int xen_pcibk_get_interrupt_type(struct pci_dev *dev); | ||
| 135 | |||
| 129 | #endif /* __XEN_PCIBACK_CONF_SPACE_H__ */ | 136 | #endif /* __XEN_PCIBACK_CONF_SPACE_H__ */ |
| @@ -189,6 +189,85 @@ static const struct config_field caplist_pm[] = { · 188 unmodified lines | |||
| 189 | {} | 189 | {} |
| 190 | }; | 190 | }; |
| 191 | 191 | ||
| 192 | static struct msi_msix_field_config { | ||
| 193 | u16 enable_bit; /* bit for enabling MSI/MSI-X */ | ||
| 194 | unsigned int int_type; /* interrupt type for exclusiveness check */ | ||
| 195 | } msi_field_config = { | ||
| 196 | .enable_bit = PCI_MSI_FLAGS_ENABLE, | ||
| 197 | .int_type = INTERRUPT_TYPE_MSI, | ||
| 198 | }, msix_field_config = { | ||
| 199 | .enable_bit = PCI_MSIX_FLAGS_ENABLE, | ||
| 200 | .int_type = INTERRUPT_TYPE_MSIX, | ||
| 201 | }; | ||
| 202 | |||
| 203 | static void *msi_field_init(struct pci_dev *dev, int offset) | ||
| 204 | { | ||
| 205 | return &msi_field_config; | ||
| 206 | } | ||
| 207 | |||
| 208 | static void *msix_field_init(struct pci_dev *dev, int offset) | ||
| 209 | { | ||
| 210 | return &msix_field_config; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int msi_msix_flags_write(struct pci_dev *dev, int offset, u16 new_value, | ||
| 214 | void *data) | ||
| 215 | { | ||
| 216 | int err; | ||
| 217 | u16 old_value; | ||
| 218 | const struct msi_msix_field_config *field_config = data; | ||
| 219 | const struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev); | ||
| 220 | |||
| 221 | if (xen_pcibk_permissive || dev_data->permissive) | ||
| 222 | goto write; | ||
| 223 | |||
| 224 | err = pci_read_config_word(dev, offset, &old_value); | ||
| 225 | if (err) | ||
| 226 | return err; | ||
| 227 | |||
| 228 | if (new_value == old_value) | ||
| 229 | return 0; | ||
| 230 | |||
| 231 | if (!dev_data->allow_interrupt_control || | ||
| 232 | (new_value ^ old_value) & ~field_config->enable_bit) | ||
| 233 | return PCIBIOS_SET_FAILED; | ||
| 234 | |||
| 235 | if (new_value & field_config->enable_bit) { | ||
| 236 | /* don't allow enabling together with other interrupt types */ | ||
| 237 | int int_type = xen_pcibk_get_interrupt_type(dev); | ||
| 238 | |||
| 239 | if (int_type == INTERRUPT_TYPE_NONE || | ||
| 240 | int_type == field_config->int_type) | ||
| 241 | goto write; | ||
| 242 | return PCIBIOS_SET_FAILED; | ||
| 243 | } | ||
| 244 | |||
| 245 | write: | ||
| 246 | return pci_write_config_word(dev, offset, new_value); | ||
| 247 | } | ||
| 248 | |||
| 249 | static const struct config_field caplist_msix[] = { | ||
| 250 | { | ||
| 251 | .offset = PCI_MSIX_FLAGS, | ||
| 252 | .size = 2, | ||
| 253 | .init = msix_field_init, | ||
| 254 | .u.w.read = xen_pcibk_read_config_word, | ||
| 255 | .u.w.write = msi_msix_flags_write, | ||
| 256 | }, | ||
| 257 | {} | ||
| 258 | }; | ||
| 259 | |||
| 260 | static const struct config_field caplist_msi[] = { | ||
| 261 | { | ||
| 262 | .offset = PCI_MSI_FLAGS, | ||
| 263 | .size = 2, | ||
| 264 | .init = msi_field_init, | ||
| 265 | .u.w.read = xen_pcibk_read_config_word, | ||
| 266 | .u.w.write = msi_msix_flags_write, | ||
| 267 | }, | ||
| 268 | {} | ||
| 269 | }; | ||
| 270 | |||
| 192 | static struct xen_pcibk_config_capability xen_pcibk_config_capability_pm = { | 271 | static struct xen_pcibk_config_capability xen_pcibk_config_capability_pm = { |
| 193 | .capability = PCI_CAP_ID_PM, | 272 | .capability = PCI_CAP_ID_PM, |
| 194 | .fields = caplist_pm, | 273 | .fields = caplist_pm, |
| @@ -197,11 +276,21 @@ static struct xen_pcibk_config_capability xen_pcibk_config_capability_vpd = { · 2 unmodified lines | |||
| 197 | .capability = PCI_CAP_ID_VPD, | 276 | .capability = PCI_CAP_ID_VPD, |
| 198 | .fields = caplist_vpd, | 277 | .fields = caplist_vpd, |
| 199 | }; | 278 | }; |
| 279 | static struct xen_pcibk_config_capability xen_pcibk_config_capability_msi = { | ||
| 280 | .capability = PCI_CAP_ID_MSI, | ||
| 281 | .fields = caplist_msi, | ||
| 282 | }; | ||
| 283 | static struct xen_pcibk_config_capability xen_pcibk_config_capability_msix = { | ||
| 284 | .capability = PCI_CAP_ID_MSIX, | ||
| 285 | .fields = caplist_msix, | ||
| 286 | }; | ||
| 200 | 287 | ||
| 201 | int xen_pcibk_config_capability_init(void) | 288 | int xen_pcibk_config_capability_init(void) |
| 202 | { | 289 | { |
| 203 | register_capability(&xen_pcibk_config_capability_vpd); | 290 | register_capability(&xen_pcibk_config_capability_vpd); |
| 204 | register_capability(&xen_pcibk_config_capability_pm); | 291 | register_capability(&xen_pcibk_config_capability_pm); |
| 292 | register_capability(&xen_pcibk_config_capability_msi); | ||
| 293 | register_capability(&xen_pcibk_config_capability_msix); | ||
| 205 | 294 | ||
| 206 | return 0; | 295 | return 0; |
| 207 | } | 296 | } |
| @@ -117,6 +117,25 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) · 116 unmodified lines | |||
| 117 | pci_clear_mwi(dev); | 117 | pci_clear_mwi(dev); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | if (dev_data && dev_data->allow_interrupt_control) { | ||
| 121 | if ((cmd->val ^ value) & PCI_COMMAND_INTX_DISABLE) { | ||
| 122 | if (value & PCI_COMMAND_INTX_DISABLE) { | ||
| 123 | pci_intx(dev, 0); | ||
| 124 | } else { | ||
| 125 | /* Do not allow enabling INTx together with MSI or MSI-X. */ | ||
| 126 | switch (xen_pcibk_get_interrupt_type(dev)) { | ||
| 127 | case INTERRUPT_TYPE_NONE: | ||
| 128 | pci_intx(dev, 1); | ||
| 129 | break; | ||
| 130 | case INTERRUPT_TYPE_INTX: | ||
| 131 | break; | ||
| 132 | default: | ||
| 133 | return PCIBIOS_SET_FAILED; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 120 | cmd->val = value; | 139 | cmd->val = value; |
| 121 | 140 | ||
| 122 | if (!xen_pcibk_permissive && (!dev_data || !dev_data->permissive)) | 141 | if (!xen_pcibk_permissive && (!dev_data || !dev_data->permissive)) |
| @@ -304,6 +304,8 @@ void pcistub_put_pci_dev(struct pci_dev *dev) · 303 unmodified lines | |||
| 304 | xen_pcibk_config_reset_dev(dev); | 304 | xen_pcibk_config_reset_dev(dev); |
| 305 | xen_pcibk_config_free_dyn_fields(dev); | 305 | xen_pcibk_config_free_dyn_fields(dev); |
| 306 | 306 | ||
| 307 | dev_data->allow_interrupt_control = 0; | ||
| 308 | |||
| 307 | xen_unregister_device_domain_owner(dev); | 309 | xen_unregister_device_domain_owner(dev); |
| 308 | 310 | ||
| 309 | spin_lock_irqsave(&found_psdev->lock, flags); | 311 | spin_lock_irqsave(&found_psdev->lock, flags); |
| @@ -1431,6 +1433,65 @@ static ssize_t permissive_show(struct device_driver *drv, char *buf) · 1121 unmodified lines | |||
| 1431 | } | 1433 | } |
| 1432 | static DRIVER_ATTR_RW(permissive); | 1434 | static DRIVER_ATTR_RW(permissive); |
| 1433 | 1435 | ||
| 1436 | static ssize_t allow_interrupt_control_store(struct device_driver *drv, | ||
| 1437 | const char *buf, size_t count) | ||
| 1438 | { | ||
| 1439 | int domain, bus, slot, func; | ||
| 1440 | int err; | ||
| 1441 | struct pcistub_device *psdev; | ||
| 1442 | struct xen_pcibk_dev_data *dev_data; | ||
| 1443 | |||
| 1444 | err = str_to_slot(buf, &domain, &bus, &slot, &func); | ||
| 1445 | if (err) | ||
| 1446 | goto out; | ||
| 1447 | |||
| 1448 | psdev = pcistub_device_find(domain, bus, slot, func); | ||
| 1449 | if (!psdev) { | ||
| 1450 | err = -ENODEV; | ||
| 1451 | goto out; | ||
| 1452 | } | ||
| 1453 | |||
| 1454 | dev_data = pci_get_drvdata(psdev->dev); | ||
| 1455 | /* the driver data for a device should never be null at this point */ | ||
| 1456 | if (!dev_data) { | ||
| 1457 | err = -ENXIO; | ||
| 1458 | goto release; | ||
| 1459 | } | ||
| 1460 | dev_data->allow_interrupt_control = 1; | ||
| 1461 | release: | ||
| 1462 | pcistub_device_put(psdev); | ||
| 1463 | out: | ||
| 1464 | if (!err) | ||
| 1465 | err = count; | ||
| 1466 | return err; | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | static ssize_t allow_interrupt_control_show(struct device_driver *drv, | ||
| 1470 | char *buf) | ||
| 1471 | { | ||
| 1472 | struct pcistub_device *psdev; | ||
| 1473 | struct xen_pcibk_dev_data *dev_data; | ||
| 1474 | size_t count = 0; | ||
| 1475 | unsigned long flags; | ||
| 1476 | |||
| 1477 | spin_lock_irqsave(&pcistub_devices_lock, flags); | ||
| 1478 | list_for_each_entry(psdev, &pcistub_devices, dev_list) { | ||
| 1479 | if (count >= PAGE_SIZE) | ||
| 1480 | break; | ||
| 1481 | if (!psdev->dev) | ||
| 1482 | continue; | ||
| 1483 | dev_data = pci_get_drvdata(psdev->dev); | ||
| 1484 | if (!dev_data || !dev_data->allow_interrupt_control) | ||
| 1485 | continue; | ||
| 1486 | count += | ||
| 1487 | scnprintf(buf + count, PAGE_SIZE - count, "%s\n", | ||
| 1488 | pci_name(psdev->dev)); | ||
| 1489 | } | ||
| 1490 | spin_unlock_irqrestore(&pcistub_devices_lock, flags); | ||
| 1491 | return count; | ||
| 1492 | } | ||
| 1493 | static DRIVER_ATTR_RW(allow_interrupt_control); | ||
| 1494 | |||
| 1434 | static void pcistub_exit(void) | 1495 | static void pcistub_exit(void) |
| 1435 | { | 1496 | { |
| 1436 | driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_new_slot); | 1497 | driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_new_slot); |
| @@ -1440,6 +1501,8 @@ static void pcistub_exit(void) · 3 unmodified lines | |||
| 1440 | driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_quirks); | 1501 | driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_quirks); |
| 1441 | driver_remove_file(&xen_pcibk_pci_driver.driver, | 1502 | driver_remove_file(&xen_pcibk_pci_driver.driver, |
| 1442 | &driver_attr_permissive); | 1503 | &driver_attr_permissive); |
| 1504 | driver_remove_file(&xen_pcibk_pci_driver.driver, | ||
| 1505 | &driver_attr_allow_interrupt_control); | ||
| 1443 | driver_remove_file(&xen_pcibk_pci_driver.driver, | 1506 | driver_remove_file(&xen_pcibk_pci_driver.driver, |
| 1444 | &driver_attr_irq_handlers); | 1507 | &driver_attr_irq_handlers); |
| 1445 | driver_remove_file(&xen_pcibk_pci_driver.driver, | 1508 | driver_remove_file(&xen_pcibk_pci_driver.driver, |
| @@ -1530,6 +1593,9 @@ static int __init pcistub_init(void) · 84 unmodified lines | |||
| 1530 | if (!err) | 1593 | if (!err) |
| 1531 | err = driver_create_file(&xen_pcibk_pci_driver.driver, | 1594 | err = driver_create_file(&xen_pcibk_pci_driver.driver, |
| 1532 | &driver_attr_permissive); | 1595 | &driver_attr_permissive); |
| 1596 | if (!err) | ||
| 1597 | err = driver_create_file(&xen_pcibk_pci_driver.driver, | ||
| 1598 | &driver_attr_allow_interrupt_control); | ||
| 1533 | 1599 | ||
| 1534 | if (!err) | 1600 | if (!err) |
| 1535 | err = driver_create_file(&xen_pcibk_pci_driver.driver, | 1601 | err = driver_create_file(&xen_pcibk_pci_driver.driver, |
| @@ -45,6 +45,7 @@ struct xen_pcibk_dev_data { · 44 unmodified lines | |||
| 45 | struct list_head config_fields; | 45 | struct list_head config_fields; |
| 46 | struct pci_saved_state *pci_saved_state; | 46 | struct pci_saved_state *pci_saved_state; |
| 47 | unsigned int permissive:1; | 47 | unsigned int permissive:1; |
| 48 | unsigned int allow_interrupt_control:1; | ||
| 48 | unsigned int warned_on_write:1; | 49 | unsigned int warned_on_write:1; |
| 49 | unsigned int enable_intx:1; | 50 | unsigned int enable_intx:1; |
| 50 | unsigned int isr_on:1; /* Whether the IRQ handler is installed. */ | 51 | unsigned int isr_on:1; /* Whether the IRQ handler is installed. */ |
| @@ -239,7 +239,9 @@ int xenbus_dev_probe(struct device *_dev) · 238 unmodified lines | |||
| 239 | goto fail; | 239 | goto fail; |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | spin_lock(&dev->reclaim_lock); | ||
| 242 | err = drv->probe(dev, id); | 243 | err = drv->probe(dev, id); |
| 244 | spin_unlock(&dev->reclaim_lock); | ||
| 243 | if (err) | 245 | if (err) |
| 244 | goto fail_put; | 246 | goto fail_put; |
| 245 | 247 | ||
| @@ -268,8 +270,11 @@ int xenbus_dev_remove(struct device *_dev) · 22 unmodified lines | |||
| 268 | 270 | ||
| 269 | free_otherend_watch(dev); | 271 | free_otherend_watch(dev); |
| 270 | 272 | ||
| 271 | if (drv->remove) | 273 | if (drv->remove) { |
| 274 | spin_lock(&dev->reclaim_lock); | ||
| 272 | drv->remove(dev); | 275 | drv->remove(dev); |
| 276 | spin_unlock(&dev->reclaim_lock); | ||
| 277 | } | ||
| 273 | 278 | ||
| 274 | module_put(drv->driver.owner); | 279 | module_put(drv->driver.owner); |
| 275 | 280 | ||
| @@ -468,6 +473,7 @@ int xenbus_probe_node(struct xen_bus_type *bus, · 192 unmodified lines | |||
| 468 | goto fail; | 473 | goto fail; |
| 469 | 474 | ||
| 470 | dev_set_name(&xendev->dev, "%s", devname); | 475 | dev_set_name(&xendev->dev, "%s", devname); |
| 476 | spin_lock_init(&xendev->reclaim_lock); | ||
| 471 | 477 | ||
| 472 | /* Register with generic device framework. */ | 478 | /* Register with generic device framework. */ |
| 473 | err = device_register(&xendev->dev); | 479 | err = device_register(&xendev->dev); |
| @@ -247,6 +247,41 @@ static int backend_probe_and_watch(struct notifier_block *notifier, · 246 unmodified lines | |||
| 247 | return NOTIFY_DONE; | 247 | return NOTIFY_DONE; |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | static int backend_reclaim_memory(struct device *dev, void *data) | ||
| 251 | { | ||
| 252 | const struct xenbus_driver *drv; | ||
| 253 | struct xenbus_device *xdev; | ||
| 254 | |||
| 255 | if (!dev->driver) | ||
| 256 | return 0; | ||
| 257 | drv = to_xenbus_driver(dev->driver); | ||
| 258 | if (drv && drv->reclaim_memory) { | ||
| 259 | xdev = to_xenbus_device(dev); | ||
| 260 | if (!spin_trylock(&xdev->reclaim_lock)) | ||
| 261 | return 0; | ||
| 262 | drv->reclaim_memory(xdev); | ||
| 263 | spin_unlock(&xdev->reclaim_lock); | ||
| 264 | } | ||
| 265 | return 0; | ||
| 266 | } | ||
| 267 | |||
| 268 | /* | ||
| 269 | * Returns 0 always because we are using shrinker to only detect memory | ||
| 270 | * pressure. | ||
| 271 | */ | ||
| 272 | static unsigned long backend_shrink_memory_count(struct shrinker *shrinker, | ||
| 273 | struct shrink_control *sc) | ||
| 274 | { | ||
| 275 | bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, | ||
| 276 | backend_reclaim_memory); | ||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | |||
| 280 | static struct shrinker backend_memory_shrinker = { | ||
| 281 | .count_objects = backend_shrink_memory_count, | ||
| 282 | .seeks = DEFAULT_SEEKS, | ||
| 283 | }; | ||
| 284 | |||
| 250 | static int __init xenbus_probe_backend_init(void) | 285 | static int __init xenbus_probe_backend_init(void) |
| 251 | { | 286 | { |
| 252 | static struct notifier_block xenstore_notifier = { | 287 | static struct notifier_block xenstore_notifier = { |
| @@ -263,6 +298,9 @@ static int __init xenbus_probe_backend_init(void) · 10 unmodified lines | |||
| 263 | 298 | ||
| 264 | register_xenstore_notifier(&xenstore_notifier); | 299 | register_xenstore_notifier(&xenstore_notifier); |
| 265 | 300 | ||
| 301 | if (register_shrinker(&backend_memory_shrinker)) | ||
| 302 | pr_warn("shrinker registration failed\n"); | ||
| 303 | |||
| 266 | return 0; | 304 | return 0; |
| 267 | } | 305 | } |
| 268 | subsys_initcall(xenbus_probe_backend_init); | 306 | subsys_initcall(xenbus_probe_backend_init); |
| @@ -76,6 +76,7 @@ struct xenbus_device { · 75 unmodified lines | |||
| 76 | enum xenbus_state state; | 76 | enum xenbus_state state; |
| 77 | struct completion down; | 77 | struct completion down; |
| 78 | struct work_struct work; | 78 | struct work_struct work; |
| 79 | spinlock_t reclaim_lock; | ||
| 79 | }; | 80 | }; |
| 80 | 81 | ||
| 81 | static inline struct xenbus_device *to_xenbus_device(struct device *dev) | 82 | static inline struct xenbus_device *to_xenbus_device(struct device *dev) |
| @@ -105,6 +106,7 @@ struct xenbus_driver { · 23 unmodified lines | |||
| 105 | struct device_driver driver; | 106 | struct device_driver driver; |
| 106 | int (*read_otherend_details)(struct xenbus_device *dev); | 107 | int (*read_otherend_details)(struct xenbus_device *dev); |
| 107 | int (*is_ready)(struct xenbus_device *dev); | 108 | int (*is_ready)(struct xenbus_device *dev); |
| 109 | void (*reclaim_memory)(struct xenbus_device *dev); | ||
| 108 | }; | 110 | }; |
| 109 | 111 | ||
| 110 | static inline struct xenbus_driver *to_xenbus_driver(struct device_driver *drv) | 112 | static inline struct xenbus_driver *to_xenbus_driver(struct device_driver *drv) |