diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-23 08:44:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-23 08:44:11 -0400 |
commit | 4ab59fcfd56670df8f9c964240e25944a1b42eef (patch) | |
tree | ed478f05fae5f40a3288048913b61569fd506048 | |
parent | 894b8c000ae6c106cc434ee0000dfb77df8bd9db (diff) | |
parent | eef04c7b3786ff0c9cb1019278b6c6c2ea0ad4ff (diff) |
Merge tag 'for-linus-4.18-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull xen fixes from Juergen Gross:
"This contains the following fixes/cleanups:
- the removal of a BUG_ON() which wasn't necessary and which could
trigger now due to a recent change
- a correction of a long standing bug happening very rarely in Xen
dom0 when a hypercall buffer from user land was not accessible by
the hypervisor for very short periods of time due to e.g. page
migration or compaction
- usage of EXPORT_SYMBOL_GPL() instead of EXPORT_SYMBOL() in a
Xen-related driver (no breakage possible as using those symbols
without others already exported via EXPORT-SYMBOL_GPL() wouldn't
make any sense)
- a simplification for Xen PVH or Xen ARM guests
- some additional error handling for callers of xenbus_printf()"
* tag 'for-linus-4.18-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
xen: Remove unnecessary BUG_ON from __unbind_from_irq()
xen: add new hypercall buffer mapping device
xen/scsiback: add error handling for xenbus_printf
scsi: xen-scsifront: add error handling for xenbus_printf
xen/grant-table: Export gnttab_{alloc|free}_pages as GPL
xen: add error handling for xenbus_printf
xen: share start flags between PV and PVH
-rw-r--r-- | arch/arm/xen/enlighten.c | 7 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 7 | ||||
-rw-r--r-- | arch/x86/xen/enlighten_pv.c | 1 | ||||
-rw-r--r-- | arch/x86/xen/enlighten_pvh.c | 1 | ||||
-rw-r--r-- | drivers/scsi/xen-scsifront.c | 33 | ||||
-rw-r--r-- | drivers/xen/Makefile | 2 | ||||
-rw-r--r-- | drivers/xen/events/events_base.c | 2 | ||||
-rw-r--r-- | drivers/xen/grant-table.c | 4 | ||||
-rw-r--r-- | drivers/xen/manage.c | 18 | ||||
-rw-r--r-- | drivers/xen/privcmd-buf.c | 210 | ||||
-rw-r--r-- | drivers/xen/privcmd.c | 9 | ||||
-rw-r--r-- | drivers/xen/privcmd.h | 3 | ||||
-rw-r--r-- | drivers/xen/xen-scsiback.c | 16 | ||||
-rw-r--r-- | include/xen/xen.h | 6 |
14 files changed, 297 insertions, 22 deletions
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 8073625371f5..07060e5b5864 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c | |||
@@ -59,6 +59,9 @@ struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata; | |||
59 | 59 | ||
60 | static __read_mostly unsigned int xen_events_irq; | 60 | static __read_mostly unsigned int xen_events_irq; |
61 | 61 | ||
62 | uint32_t xen_start_flags; | ||
63 | EXPORT_SYMBOL(xen_start_flags); | ||
64 | |||
62 | int xen_remap_domain_gfn_array(struct vm_area_struct *vma, | 65 | int xen_remap_domain_gfn_array(struct vm_area_struct *vma, |
63 | unsigned long addr, | 66 | unsigned long addr, |
64 | xen_pfn_t *gfn, int nr, | 67 | xen_pfn_t *gfn, int nr, |
@@ -293,9 +296,7 @@ void __init xen_early_init(void) | |||
293 | xen_setup_features(); | 296 | xen_setup_features(); |
294 | 297 | ||
295 | if (xen_feature(XENFEAT_dom0)) | 298 | if (xen_feature(XENFEAT_dom0)) |
296 | xen_start_info->flags |= SIF_INITDOMAIN|SIF_PRIVILEGED; | 299 | xen_start_flags |= SIF_INITDOMAIN|SIF_PRIVILEGED; |
297 | else | ||
298 | xen_start_info->flags &= ~(SIF_INITDOMAIN|SIF_PRIVILEGED); | ||
299 | 300 | ||
300 | if (!console_set_on_cmdline && !xen_initial_domain()) | 301 | if (!console_set_on_cmdline && !xen_initial_domain()) |
301 | add_preferred_console("hvc", 0, NULL); | 302 | add_preferred_console("hvc", 0, NULL); |
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index c9081c6671f0..3b5318505c69 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -65,6 +65,13 @@ __read_mostly int xen_have_vector_callback; | |||
65 | EXPORT_SYMBOL_GPL(xen_have_vector_callback); | 65 | EXPORT_SYMBOL_GPL(xen_have_vector_callback); |
66 | 66 | ||
67 | /* | 67 | /* |
68 | * NB: needs to live in .data because it's used by xen_prepare_pvh which runs | ||
69 | * before clearing the bss. | ||
70 | */ | ||
71 | uint32_t xen_start_flags __attribute__((section(".data"))) = 0; | ||
72 | EXPORT_SYMBOL(xen_start_flags); | ||
73 | |||
74 | /* | ||
68 | * Point at some empty memory to start with. We map the real shared_info | 75 | * Point at some empty memory to start with. We map the real shared_info |
69 | * page as soon as fixmap is up and running. | 76 | * page as soon as fixmap is up and running. |
70 | */ | 77 | */ |
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index 357969a3697c..8d4e2e1ae60b 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c | |||
@@ -1203,6 +1203,7 @@ asmlinkage __visible void __init xen_start_kernel(void) | |||
1203 | return; | 1203 | return; |
1204 | 1204 | ||
1205 | xen_domain_type = XEN_PV_DOMAIN; | 1205 | xen_domain_type = XEN_PV_DOMAIN; |
1206 | xen_start_flags = xen_start_info->flags; | ||
1206 | 1207 | ||
1207 | xen_setup_features(); | 1208 | xen_setup_features(); |
1208 | 1209 | ||
diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c index aa1c6a6831a9..c85d1a88f476 100644 --- a/arch/x86/xen/enlighten_pvh.c +++ b/arch/x86/xen/enlighten_pvh.c | |||
@@ -97,6 +97,7 @@ void __init xen_prepare_pvh(void) | |||
97 | } | 97 | } |
98 | 98 | ||
99 | xen_pvh = 1; | 99 | xen_pvh = 1; |
100 | xen_start_flags = pvh_start_info.flags; | ||
100 | 101 | ||
101 | msr = cpuid_ebx(xen_cpuid_base() + 2); | 102 | msr = cpuid_ebx(xen_cpuid_base() + 2); |
102 | pfn = __pa(hypercall_page); | 103 | pfn = __pa(hypercall_page); |
diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c index 36f59a1be7e9..61389bdc7926 100644 --- a/drivers/scsi/xen-scsifront.c +++ b/drivers/scsi/xen-scsifront.c | |||
@@ -654,10 +654,17 @@ static int scsifront_dev_reset_handler(struct scsi_cmnd *sc) | |||
654 | static int scsifront_sdev_configure(struct scsi_device *sdev) | 654 | static int scsifront_sdev_configure(struct scsi_device *sdev) |
655 | { | 655 | { |
656 | struct vscsifrnt_info *info = shost_priv(sdev->host); | 656 | struct vscsifrnt_info *info = shost_priv(sdev->host); |
657 | int err; | ||
657 | 658 | ||
658 | if (info && current == info->curr) | 659 | if (info && current == info->curr) { |
659 | xenbus_printf(XBT_NIL, info->dev->nodename, | 660 | err = xenbus_printf(XBT_NIL, info->dev->nodename, |
660 | info->dev_state_path, "%d", XenbusStateConnected); | 661 | info->dev_state_path, "%d", XenbusStateConnected); |
662 | if (err) { | ||
663 | xenbus_dev_error(info->dev, err, | ||
664 | "%s: writing dev_state_path", __func__); | ||
665 | return err; | ||
666 | } | ||
667 | } | ||
661 | 668 | ||
662 | return 0; | 669 | return 0; |
663 | } | 670 | } |
@@ -665,10 +672,15 @@ static int scsifront_sdev_configure(struct scsi_device *sdev) | |||
665 | static void scsifront_sdev_destroy(struct scsi_device *sdev) | 672 | static void scsifront_sdev_destroy(struct scsi_device *sdev) |
666 | { | 673 | { |
667 | struct vscsifrnt_info *info = shost_priv(sdev->host); | 674 | struct vscsifrnt_info *info = shost_priv(sdev->host); |
675 | int err; | ||
668 | 676 | ||
669 | if (info && current == info->curr) | 677 | if (info && current == info->curr) { |
670 | xenbus_printf(XBT_NIL, info->dev->nodename, | 678 | err = xenbus_printf(XBT_NIL, info->dev->nodename, |
671 | info->dev_state_path, "%d", XenbusStateClosed); | 679 | info->dev_state_path, "%d", XenbusStateClosed); |
680 | if (err) | ||
681 | xenbus_dev_error(info->dev, err, | ||
682 | "%s: writing dev_state_path", __func__); | ||
683 | } | ||
672 | } | 684 | } |
673 | 685 | ||
674 | static struct scsi_host_template scsifront_sht = { | 686 | static struct scsi_host_template scsifront_sht = { |
@@ -1003,9 +1015,12 @@ static void scsifront_do_lun_hotplug(struct vscsifrnt_info *info, int op) | |||
1003 | 1015 | ||
1004 | if (scsi_add_device(info->host, chn, tgt, lun)) { | 1016 | if (scsi_add_device(info->host, chn, tgt, lun)) { |
1005 | dev_err(&dev->dev, "scsi_add_device\n"); | 1017 | dev_err(&dev->dev, "scsi_add_device\n"); |
1006 | xenbus_printf(XBT_NIL, dev->nodename, | 1018 | err = xenbus_printf(XBT_NIL, dev->nodename, |
1007 | info->dev_state_path, | 1019 | info->dev_state_path, |
1008 | "%d", XenbusStateClosed); | 1020 | "%d", XenbusStateClosed); |
1021 | if (err) | ||
1022 | xenbus_dev_error(dev, err, | ||
1023 | "%s: writing dev_state_path", __func__); | ||
1009 | } | 1024 | } |
1010 | break; | 1025 | break; |
1011 | case VSCSIFRONT_OP_DEL_LUN: | 1026 | case VSCSIFRONT_OP_DEL_LUN: |
@@ -1019,10 +1034,14 @@ static void scsifront_do_lun_hotplug(struct vscsifrnt_info *info, int op) | |||
1019 | } | 1034 | } |
1020 | break; | 1035 | break; |
1021 | case VSCSIFRONT_OP_READD_LUN: | 1036 | case VSCSIFRONT_OP_READD_LUN: |
1022 | if (device_state == XenbusStateConnected) | 1037 | if (device_state == XenbusStateConnected) { |
1023 | xenbus_printf(XBT_NIL, dev->nodename, | 1038 | err = xenbus_printf(XBT_NIL, dev->nodename, |
1024 | info->dev_state_path, | 1039 | info->dev_state_path, |
1025 | "%d", XenbusStateConnected); | 1040 | "%d", XenbusStateConnected); |
1041 | if (err) | ||
1042 | xenbus_dev_error(dev, err, | ||
1043 | "%s: writing dev_state_path", __func__); | ||
1044 | } | ||
1026 | break; | 1045 | break; |
1027 | default: | 1046 | default: |
1028 | break; | 1047 | break; |
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 451e833f5931..48b154276179 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile | |||
@@ -41,4 +41,4 @@ obj-$(CONFIG_XEN_PVCALLS_FRONTEND) += pvcalls-front.o | |||
41 | xen-evtchn-y := evtchn.o | 41 | xen-evtchn-y := evtchn.o |
42 | xen-gntdev-y := gntdev.o | 42 | xen-gntdev-y := gntdev.o |
43 | xen-gntalloc-y := gntalloc.o | 43 | xen-gntalloc-y := gntalloc.o |
44 | xen-privcmd-y := privcmd.o | 44 | xen-privcmd-y := privcmd.o privcmd-buf.o |
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index 762378f1811c..08e4af04d6f2 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c | |||
@@ -628,8 +628,6 @@ static void __unbind_from_irq(unsigned int irq) | |||
628 | xen_irq_info_cleanup(info); | 628 | xen_irq_info_cleanup(info); |
629 | } | 629 | } |
630 | 630 | ||
631 | BUG_ON(info_for_irq(irq)->type == IRQT_UNBOUND); | ||
632 | |||
633 | xen_free_irq(irq); | 631 | xen_free_irq(irq); |
634 | } | 632 | } |
635 | 633 | ||
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 2473b0a9e6e4..ba9f3eec2bd0 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -799,7 +799,7 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages) | |||
799 | 799 | ||
800 | return 0; | 800 | return 0; |
801 | } | 801 | } |
802 | EXPORT_SYMBOL(gnttab_alloc_pages); | 802 | EXPORT_SYMBOL_GPL(gnttab_alloc_pages); |
803 | 803 | ||
804 | /** | 804 | /** |
805 | * gnttab_free_pages - free pages allocated by gnttab_alloc_pages() | 805 | * gnttab_free_pages - free pages allocated by gnttab_alloc_pages() |
@@ -820,7 +820,7 @@ void gnttab_free_pages(int nr_pages, struct page **pages) | |||
820 | } | 820 | } |
821 | free_xenballooned_pages(nr_pages, pages); | 821 | free_xenballooned_pages(nr_pages, pages); |
822 | } | 822 | } |
823 | EXPORT_SYMBOL(gnttab_free_pages); | 823 | EXPORT_SYMBOL_GPL(gnttab_free_pages); |
824 | 824 | ||
825 | /* Handling of paged out grant targets (GNTST_eagain) */ | 825 | /* Handling of paged out grant targets (GNTST_eagain) */ |
826 | #define MAX_DELAY 256 | 826 | #define MAX_DELAY 256 |
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 8835065029d3..c93d8ef8df34 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
@@ -289,8 +289,15 @@ static void sysrq_handler(struct xenbus_watch *watch, const char *path, | |||
289 | return; | 289 | return; |
290 | } | 290 | } |
291 | 291 | ||
292 | if (sysrq_key != '\0') | 292 | if (sysrq_key != '\0') { |
293 | xenbus_printf(xbt, "control", "sysrq", "%c", '\0'); | 293 | err = xenbus_printf(xbt, "control", "sysrq", "%c", '\0'); |
294 | if (err) { | ||
295 | pr_err("%s: Error %d writing sysrq in control/sysrq\n", | ||
296 | __func__, err); | ||
297 | xenbus_transaction_end(xbt, 1); | ||
298 | return; | ||
299 | } | ||
300 | } | ||
294 | 301 | ||
295 | err = xenbus_transaction_end(xbt, 0); | 302 | err = xenbus_transaction_end(xbt, 0); |
296 | if (err == -EAGAIN) | 303 | if (err == -EAGAIN) |
@@ -342,7 +349,12 @@ static int setup_shutdown_watcher(void) | |||
342 | continue; | 349 | continue; |
343 | snprintf(node, FEATURE_PATH_SIZE, "feature-%s", | 350 | snprintf(node, FEATURE_PATH_SIZE, "feature-%s", |
344 | shutdown_handlers[idx].command); | 351 | shutdown_handlers[idx].command); |
345 | xenbus_printf(XBT_NIL, "control", node, "%u", 1); | 352 | err = xenbus_printf(XBT_NIL, "control", node, "%u", 1); |
353 | if (err) { | ||
354 | pr_err("%s: Error %d writing %s\n", __func__, | ||
355 | err, node); | ||
356 | return err; | ||
357 | } | ||
346 | } | 358 | } |
347 | 359 | ||
348 | return 0; | 360 | return 0; |
diff --git a/drivers/xen/privcmd-buf.c b/drivers/xen/privcmd-buf.c new file mode 100644 index 000000000000..df1ed37c3269 --- /dev/null +++ b/drivers/xen/privcmd-buf.c | |||
@@ -0,0 +1,210 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 OR MIT | ||
2 | |||
3 | /****************************************************************************** | ||
4 | * privcmd-buf.c | ||
5 | * | ||
6 | * Mmap of hypercall buffers. | ||
7 | * | ||
8 | * Copyright (c) 2018 Juergen Gross | ||
9 | */ | ||
10 | |||
11 | #define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/list.h> | ||
16 | #include <linux/miscdevice.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/slab.h> | ||
19 | |||
20 | #include "privcmd.h" | ||
21 | |||
22 | MODULE_LICENSE("GPL"); | ||
23 | |||
24 | static unsigned int limit = 64; | ||
25 | module_param(limit, uint, 0644); | ||
26 | MODULE_PARM_DESC(limit, "Maximum number of pages that may be allocated by " | ||
27 | "the privcmd-buf device per open file"); | ||
28 | |||
29 | struct privcmd_buf_private { | ||
30 | struct mutex lock; | ||
31 | struct list_head list; | ||
32 | unsigned int allocated; | ||
33 | }; | ||
34 | |||
35 | struct privcmd_buf_vma_private { | ||
36 | struct privcmd_buf_private *file_priv; | ||
37 | struct list_head list; | ||
38 | unsigned int users; | ||
39 | unsigned int n_pages; | ||
40 | struct page *pages[]; | ||
41 | }; | ||
42 | |||
43 | static int privcmd_buf_open(struct inode *ino, struct file *file) | ||
44 | { | ||
45 | struct privcmd_buf_private *file_priv; | ||
46 | |||
47 | file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); | ||
48 | if (!file_priv) | ||
49 | return -ENOMEM; | ||
50 | |||
51 | mutex_init(&file_priv->lock); | ||
52 | INIT_LIST_HEAD(&file_priv->list); | ||
53 | |||
54 | file->private_data = file_priv; | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static void privcmd_buf_vmapriv_free(struct privcmd_buf_vma_private *vma_priv) | ||
60 | { | ||
61 | unsigned int i; | ||
62 | |||
63 | vma_priv->file_priv->allocated -= vma_priv->n_pages; | ||
64 | |||
65 | list_del(&vma_priv->list); | ||
66 | |||
67 | for (i = 0; i < vma_priv->n_pages; i++) | ||
68 | if (vma_priv->pages[i]) | ||
69 | __free_page(vma_priv->pages[i]); | ||
70 | |||
71 | kfree(vma_priv); | ||
72 | } | ||
73 | |||
74 | static int privcmd_buf_release(struct inode *ino, struct file *file) | ||
75 | { | ||
76 | struct privcmd_buf_private *file_priv = file->private_data; | ||
77 | struct privcmd_buf_vma_private *vma_priv; | ||
78 | |||
79 | mutex_lock(&file_priv->lock); | ||
80 | |||
81 | while (!list_empty(&file_priv->list)) { | ||
82 | vma_priv = list_first_entry(&file_priv->list, | ||
83 | struct privcmd_buf_vma_private, | ||
84 | list); | ||
85 | privcmd_buf_vmapriv_free(vma_priv); | ||
86 | } | ||
87 | |||
88 | mutex_unlock(&file_priv->lock); | ||
89 | |||
90 | kfree(file_priv); | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static void privcmd_buf_vma_open(struct vm_area_struct *vma) | ||
96 | { | ||
97 | struct privcmd_buf_vma_private *vma_priv = vma->vm_private_data; | ||
98 | |||
99 | if (!vma_priv) | ||
100 | return; | ||
101 | |||
102 | mutex_lock(&vma_priv->file_priv->lock); | ||
103 | vma_priv->users++; | ||
104 | mutex_unlock(&vma_priv->file_priv->lock); | ||
105 | } | ||
106 | |||
107 | static void privcmd_buf_vma_close(struct vm_area_struct *vma) | ||
108 | { | ||
109 | struct privcmd_buf_vma_private *vma_priv = vma->vm_private_data; | ||
110 | struct privcmd_buf_private *file_priv; | ||
111 | |||
112 | if (!vma_priv) | ||
113 | return; | ||
114 | |||
115 | file_priv = vma_priv->file_priv; | ||
116 | |||
117 | mutex_lock(&file_priv->lock); | ||
118 | |||
119 | vma_priv->users--; | ||
120 | if (!vma_priv->users) | ||
121 | privcmd_buf_vmapriv_free(vma_priv); | ||
122 | |||
123 | mutex_unlock(&file_priv->lock); | ||
124 | } | ||
125 | |||
126 | static vm_fault_t privcmd_buf_vma_fault(struct vm_fault *vmf) | ||
127 | { | ||
128 | pr_debug("fault: vma=%p %lx-%lx, pgoff=%lx, uv=%p\n", | ||
129 | vmf->vma, vmf->vma->vm_start, vmf->vma->vm_end, | ||
130 | vmf->pgoff, (void *)vmf->address); | ||
131 | |||
132 | return VM_FAULT_SIGBUS; | ||
133 | } | ||
134 | |||
135 | static const struct vm_operations_struct privcmd_buf_vm_ops = { | ||
136 | .open = privcmd_buf_vma_open, | ||
137 | .close = privcmd_buf_vma_close, | ||
138 | .fault = privcmd_buf_vma_fault, | ||
139 | }; | ||
140 | |||
141 | static int privcmd_buf_mmap(struct file *file, struct vm_area_struct *vma) | ||
142 | { | ||
143 | struct privcmd_buf_private *file_priv = file->private_data; | ||
144 | struct privcmd_buf_vma_private *vma_priv; | ||
145 | unsigned long count = vma_pages(vma); | ||
146 | unsigned int i; | ||
147 | int ret = 0; | ||
148 | |||
149 | if (!(vma->vm_flags & VM_SHARED) || count > limit || | ||
150 | file_priv->allocated + count > limit) | ||
151 | return -EINVAL; | ||
152 | |||
153 | vma_priv = kzalloc(sizeof(*vma_priv) + count * sizeof(void *), | ||
154 | GFP_KERNEL); | ||
155 | if (!vma_priv) | ||
156 | return -ENOMEM; | ||
157 | |||
158 | vma_priv->n_pages = count; | ||
159 | count = 0; | ||
160 | for (i = 0; i < vma_priv->n_pages; i++) { | ||
161 | vma_priv->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO); | ||
162 | if (!vma_priv->pages[i]) | ||
163 | break; | ||
164 | count++; | ||
165 | } | ||
166 | |||
167 | mutex_lock(&file_priv->lock); | ||
168 | |||
169 | file_priv->allocated += count; | ||
170 | |||
171 | vma_priv->file_priv = file_priv; | ||
172 | vma_priv->users = 1; | ||
173 | |||
174 | vma->vm_flags |= VM_IO | VM_DONTEXPAND; | ||
175 | vma->vm_ops = &privcmd_buf_vm_ops; | ||
176 | vma->vm_private_data = vma_priv; | ||
177 | |||
178 | list_add(&vma_priv->list, &file_priv->list); | ||
179 | |||
180 | if (vma_priv->n_pages != count) | ||
181 | ret = -ENOMEM; | ||
182 | else | ||
183 | for (i = 0; i < vma_priv->n_pages; i++) { | ||
184 | ret = vm_insert_page(vma, vma->vm_start + i * PAGE_SIZE, | ||
185 | vma_priv->pages[i]); | ||
186 | if (ret) | ||
187 | break; | ||
188 | } | ||
189 | |||
190 | if (ret) | ||
191 | privcmd_buf_vmapriv_free(vma_priv); | ||
192 | |||
193 | mutex_unlock(&file_priv->lock); | ||
194 | |||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | const struct file_operations xen_privcmdbuf_fops = { | ||
199 | .owner = THIS_MODULE, | ||
200 | .open = privcmd_buf_open, | ||
201 | .release = privcmd_buf_release, | ||
202 | .mmap = privcmd_buf_mmap, | ||
203 | }; | ||
204 | EXPORT_SYMBOL_GPL(xen_privcmdbuf_fops); | ||
205 | |||
206 | struct miscdevice xen_privcmdbuf_dev = { | ||
207 | .minor = MISC_DYNAMIC_MINOR, | ||
208 | .name = "xen/hypercall", | ||
209 | .fops = &xen_privcmdbuf_fops, | ||
210 | }; | ||
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 8ae0349d9f0a..7e6e682104dc 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c | |||
@@ -1007,12 +1007,21 @@ static int __init privcmd_init(void) | |||
1007 | pr_err("Could not register Xen privcmd device\n"); | 1007 | pr_err("Could not register Xen privcmd device\n"); |
1008 | return err; | 1008 | return err; |
1009 | } | 1009 | } |
1010 | |||
1011 | err = misc_register(&xen_privcmdbuf_dev); | ||
1012 | if (err != 0) { | ||
1013 | pr_err("Could not register Xen hypercall-buf device\n"); | ||
1014 | misc_deregister(&privcmd_dev); | ||
1015 | return err; | ||
1016 | } | ||
1017 | |||
1010 | return 0; | 1018 | return 0; |
1011 | } | 1019 | } |
1012 | 1020 | ||
1013 | static void __exit privcmd_exit(void) | 1021 | static void __exit privcmd_exit(void) |
1014 | { | 1022 | { |
1015 | misc_deregister(&privcmd_dev); | 1023 | misc_deregister(&privcmd_dev); |
1024 | misc_deregister(&xen_privcmdbuf_dev); | ||
1016 | } | 1025 | } |
1017 | 1026 | ||
1018 | module_init(privcmd_init); | 1027 | module_init(privcmd_init); |
diff --git a/drivers/xen/privcmd.h b/drivers/xen/privcmd.h index 14facaeed36f..0dd9f8f67ee3 100644 --- a/drivers/xen/privcmd.h +++ b/drivers/xen/privcmd.h | |||
@@ -1,3 +1,6 @@ | |||
1 | #include <linux/fs.h> | 1 | #include <linux/fs.h> |
2 | 2 | ||
3 | extern const struct file_operations xen_privcmd_fops; | 3 | extern const struct file_operations xen_privcmd_fops; |
4 | extern const struct file_operations xen_privcmdbuf_fops; | ||
5 | |||
6 | extern struct miscdevice xen_privcmdbuf_dev; | ||
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c index 7bc88fd43cfc..e2f3e8b0fba9 100644 --- a/drivers/xen/xen-scsiback.c +++ b/drivers/xen/xen-scsiback.c | |||
@@ -1012,6 +1012,7 @@ static void scsiback_do_add_lun(struct vscsibk_info *info, const char *state, | |||
1012 | { | 1012 | { |
1013 | struct v2p_entry *entry; | 1013 | struct v2p_entry *entry; |
1014 | unsigned long flags; | 1014 | unsigned long flags; |
1015 | int err; | ||
1015 | 1016 | ||
1016 | if (try) { | 1017 | if (try) { |
1017 | spin_lock_irqsave(&info->v2p_lock, flags); | 1018 | spin_lock_irqsave(&info->v2p_lock, flags); |
@@ -1027,8 +1028,11 @@ static void scsiback_do_add_lun(struct vscsibk_info *info, const char *state, | |||
1027 | scsiback_del_translation_entry(info, vir); | 1028 | scsiback_del_translation_entry(info, vir); |
1028 | } | 1029 | } |
1029 | } else if (!try) { | 1030 | } else if (!try) { |
1030 | xenbus_printf(XBT_NIL, info->dev->nodename, state, | 1031 | err = xenbus_printf(XBT_NIL, info->dev->nodename, state, |
1031 | "%d", XenbusStateClosed); | 1032 | "%d", XenbusStateClosed); |
1033 | if (err) | ||
1034 | xenbus_dev_error(info->dev, err, | ||
1035 | "%s: writing %s", __func__, state); | ||
1032 | } | 1036 | } |
1033 | } | 1037 | } |
1034 | 1038 | ||
@@ -1067,8 +1071,11 @@ static void scsiback_do_1lun_hotplug(struct vscsibk_info *info, int op, | |||
1067 | snprintf(str, sizeof(str), "vscsi-devs/%s/p-dev", ent); | 1071 | snprintf(str, sizeof(str), "vscsi-devs/%s/p-dev", ent); |
1068 | val = xenbus_read(XBT_NIL, dev->nodename, str, NULL); | 1072 | val = xenbus_read(XBT_NIL, dev->nodename, str, NULL); |
1069 | if (IS_ERR(val)) { | 1073 | if (IS_ERR(val)) { |
1070 | xenbus_printf(XBT_NIL, dev->nodename, state, | 1074 | err = xenbus_printf(XBT_NIL, dev->nodename, state, |
1071 | "%d", XenbusStateClosed); | 1075 | "%d", XenbusStateClosed); |
1076 | if (err) | ||
1077 | xenbus_dev_error(info->dev, err, | ||
1078 | "%s: writing %s", __func__, state); | ||
1072 | return; | 1079 | return; |
1073 | } | 1080 | } |
1074 | strlcpy(phy, val, VSCSI_NAMELEN); | 1081 | strlcpy(phy, val, VSCSI_NAMELEN); |
@@ -1079,8 +1086,11 @@ static void scsiback_do_1lun_hotplug(struct vscsibk_info *info, int op, | |||
1079 | err = xenbus_scanf(XBT_NIL, dev->nodename, str, "%u:%u:%u:%u", | 1086 | err = xenbus_scanf(XBT_NIL, dev->nodename, str, "%u:%u:%u:%u", |
1080 | &vir.hst, &vir.chn, &vir.tgt, &vir.lun); | 1087 | &vir.hst, &vir.chn, &vir.tgt, &vir.lun); |
1081 | if (XENBUS_EXIST_ERR(err)) { | 1088 | if (XENBUS_EXIST_ERR(err)) { |
1082 | xenbus_printf(XBT_NIL, dev->nodename, state, | 1089 | err = xenbus_printf(XBT_NIL, dev->nodename, state, |
1083 | "%d", XenbusStateClosed); | 1090 | "%d", XenbusStateClosed); |
1091 | if (err) | ||
1092 | xenbus_dev_error(info->dev, err, | ||
1093 | "%s: writing %s", __func__, state); | ||
1084 | return; | 1094 | return; |
1085 | } | 1095 | } |
1086 | 1096 | ||
diff --git a/include/xen/xen.h b/include/xen/xen.h index 9d4340c907d1..1e1d9bd0bd37 100644 --- a/include/xen/xen.h +++ b/include/xen/xen.h | |||
@@ -25,12 +25,16 @@ extern bool xen_pvh; | |||
25 | #define xen_hvm_domain() (xen_domain_type == XEN_HVM_DOMAIN) | 25 | #define xen_hvm_domain() (xen_domain_type == XEN_HVM_DOMAIN) |
26 | #define xen_pvh_domain() (xen_pvh) | 26 | #define xen_pvh_domain() (xen_pvh) |
27 | 27 | ||
28 | #include <linux/types.h> | ||
29 | |||
30 | extern uint32_t xen_start_flags; | ||
31 | |||
28 | #ifdef CONFIG_XEN_DOM0 | 32 | #ifdef CONFIG_XEN_DOM0 |
29 | #include <xen/interface/xen.h> | 33 | #include <xen/interface/xen.h> |
30 | #include <asm/xen/hypervisor.h> | 34 | #include <asm/xen/hypervisor.h> |
31 | 35 | ||
32 | #define xen_initial_domain() (xen_domain() && \ | 36 | #define xen_initial_domain() (xen_domain() && \ |
33 | xen_start_info && xen_start_info->flags & SIF_INITDOMAIN) | 37 | (xen_start_flags & SIF_INITDOMAIN)) |
34 | #else /* !CONFIG_XEN_DOM0 */ | 38 | #else /* !CONFIG_XEN_DOM0 */ |
35 | #define xen_initial_domain() (0) | 39 | #define xen_initial_domain() (0) |
36 | #endif /* CONFIG_XEN_DOM0 */ | 40 | #endif /* CONFIG_XEN_DOM0 */ |