aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-13 17:29:16 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-13 17:29:16 -0500
commit896ea17d3da5f44b2625c9cda9874d7dfe447393 (patch)
tree089f00dd300a49c81f042e9b52ef32cd1333bdbc /drivers/xen
parentc7708fac5a878d6e0f2de0aa19f9749cff4f707f (diff)
parent6a7ed405114b2a53ccd99631b0636aaeabf71b3e (diff)
Merge tag 'stable/for-linus-3.8-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen
Pull Xen updates from Konrad Rzeszutek Wilk: - Add necessary infrastructure to make balloon driver work under ARM. - Add /dev/xen/privcmd interfaces to work with ARM and PVH. - Improve Xen PCIBack wild-card parsing. - Add Xen ACPI PAD (Processor Aggregator) support - so can offline/ online sockets depending on the power consumption. - PVHVM + kexec = use an E820_RESV region for the shared region so we don't overwrite said region during kexec reboot. - Cleanups, compile fixes. Fix up some trivial conflicts due to the balloon driver now working on ARM, and there were changes next to the previous work-arounds that are now gone. * tag 'stable/for-linus-3.8-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen: xen/PVonHVM: fix compile warning in init_hvm_pv_info xen: arm: implement remap interfaces needed for privcmd mappings. xen: correctly use xen_pfn_t in remap_domain_mfn_range. xen: arm: enable balloon driver xen: balloon: allow PVMMU interfaces to be compiled out xen: privcmd: support autotranslated physmap guests. xen: add pages parameter to xen_remap_domain_mfn_range xen/acpi: Move the xen_running_on_version_or_later function. xen/xenbus: Remove duplicate inclusion of asm/xen/hypervisor.h xen/acpi: Fix compile error by missing decleration for xen_domain. xen/acpi: revert pad config check in xen_check_mwait xen/acpi: ACPI PAD driver xen-pciback: reject out of range inputs xen-pciback: simplify and tighten parsing of device IDs xen PVonHVM: use E820_Reserved area for shared_info
Diffstat (limited to 'drivers/xen')
-rw-r--r--drivers/xen/Kconfig3
-rw-r--r--drivers/xen/Makefile7
-rw-r--r--drivers/xen/balloon.c5
-rw-r--r--drivers/xen/privcmd.c72
-rw-r--r--drivers/xen/xen-acpi-pad.c182
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c118
-rw-r--r--drivers/xen/xenbus/xenbus_xs.c1
7 files changed, 326 insertions, 62 deletions
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index 126d8ce591c..cabfa97f467 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -206,4 +206,7 @@ config XEN_MCE_LOG
206 Allow kernel fetching MCE error from Xen platform and 206 Allow kernel fetching MCE error from Xen platform and
207 converting it into Linux mcelog format for mcelog tools 207 converting it into Linux mcelog format for mcelog tools
208 208
209config XEN_HAVE_PVMMU
210 bool
211
209endmenu 212endmenu
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 74354708c6c..fb213cf81a7 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -1,9 +1,9 @@
1ifneq ($(CONFIG_ARM),y) 1ifneq ($(CONFIG_ARM),y)
2obj-y += manage.o balloon.o 2obj-y += manage.o
3obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o 3obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
4endif 4endif
5obj-$(CONFIG_X86) += fallback.o 5obj-$(CONFIG_X86) += fallback.o
6obj-y += grant-table.o features.o events.o 6obj-y += grant-table.o features.o events.o balloon.o
7obj-y += xenbus/ 7obj-y += xenbus/
8 8
9nostackp := $(call cc-option, -fno-stack-protector) 9nostackp := $(call cc-option, -fno-stack-protector)
@@ -11,7 +11,8 @@ CFLAGS_features.o := $(nostackp)
11 11
12dom0-$(CONFIG_PCI) += pci.o 12dom0-$(CONFIG_PCI) += pci.o
13dom0-$(CONFIG_USB_SUPPORT) += dbgp.o 13dom0-$(CONFIG_USB_SUPPORT) += dbgp.o
14dom0-$(CONFIG_ACPI) += acpi.o 14dom0-$(CONFIG_ACPI) += acpi.o $(xen-pad-y)
15xen-pad-$(CONFIG_X86) += xen-acpi-pad.o
15dom0-$(CONFIG_X86) += pcpu.o 16dom0-$(CONFIG_X86) += pcpu.o
16obj-$(CONFIG_XEN_DOM0) += $(dom0-y) 17obj-$(CONFIG_XEN_DOM0) += $(dom0-y)
17obj-$(CONFIG_BLOCK) += biomerge.o 18obj-$(CONFIG_BLOCK) += biomerge.o
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index d6886d90ccf..a56776dbe09 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -359,6 +359,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
359 359
360 set_phys_to_machine(pfn, frame_list[i]); 360 set_phys_to_machine(pfn, frame_list[i]);
361 361
362#ifdef CONFIG_XEN_HAVE_PVMMU
362 /* Link back into the page tables if not highmem. */ 363 /* Link back into the page tables if not highmem. */
363 if (xen_pv_domain() && !PageHighMem(page)) { 364 if (xen_pv_domain() && !PageHighMem(page)) {
364 int ret; 365 int ret;
@@ -368,6 +369,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
368 0); 369 0);
369 BUG_ON(ret); 370 BUG_ON(ret);
370 } 371 }
372#endif
371 373
372 /* Relinquish the page back to the allocator. */ 374 /* Relinquish the page back to the allocator. */
373 ClearPageReserved(page); 375 ClearPageReserved(page);
@@ -416,13 +418,14 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
416 418
417 scrub_page(page); 419 scrub_page(page);
418 420
421#ifdef CONFIG_XEN_HAVE_PVMMU
419 if (xen_pv_domain() && !PageHighMem(page)) { 422 if (xen_pv_domain() && !PageHighMem(page)) {
420 ret = HYPERVISOR_update_va_mapping( 423 ret = HYPERVISOR_update_va_mapping(
421 (unsigned long)__va(pfn << PAGE_SHIFT), 424 (unsigned long)__va(pfn << PAGE_SHIFT),
422 __pte_ma(0), 0); 425 __pte_ma(0), 0);
423 BUG_ON(ret); 426 BUG_ON(ret);
424 } 427 }
425 428#endif
426 } 429 }
427 430
428 /* Ensure that ballooned highmem pages don't have kmaps. */ 431 /* Ensure that ballooned highmem pages don't have kmaps. */
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 71f5c459b08..0bbbccbb1f1 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -33,11 +33,14 @@
33#include <xen/features.h> 33#include <xen/features.h>
34#include <xen/page.h> 34#include <xen/page.h>
35#include <xen/xen-ops.h> 35#include <xen/xen-ops.h>
36#include <xen/balloon.h>
36 37
37#include "privcmd.h" 38#include "privcmd.h"
38 39
39MODULE_LICENSE("GPL"); 40MODULE_LICENSE("GPL");
40 41
42#define PRIV_VMA_LOCKED ((void *)1)
43
41#ifndef HAVE_ARCH_PRIVCMD_MMAP 44#ifndef HAVE_ARCH_PRIVCMD_MMAP
42static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma); 45static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma);
43#endif 46#endif
@@ -178,7 +181,7 @@ static int mmap_mfn_range(void *data, void *state)
178 msg->va & PAGE_MASK, 181 msg->va & PAGE_MASK,
179 msg->mfn, msg->npages, 182 msg->mfn, msg->npages,
180 vma->vm_page_prot, 183 vma->vm_page_prot,
181 st->domain); 184 st->domain, NULL);
182 if (rc < 0) 185 if (rc < 0)
183 return rc; 186 return rc;
184 187
@@ -199,6 +202,10 @@ static long privcmd_ioctl_mmap(void __user *udata)
199 if (!xen_initial_domain()) 202 if (!xen_initial_domain())
200 return -EPERM; 203 return -EPERM;
201 204
205 /* We only support privcmd_ioctl_mmap_batch for auto translated. */
206 if (xen_feature(XENFEAT_auto_translated_physmap))
207 return -ENOSYS;
208
202 if (copy_from_user(&mmapcmd, udata, sizeof(mmapcmd))) 209 if (copy_from_user(&mmapcmd, udata, sizeof(mmapcmd)))
203 return -EFAULT; 210 return -EFAULT;
204 211
@@ -246,6 +253,7 @@ struct mmap_batch_state {
246 domid_t domain; 253 domid_t domain;
247 unsigned long va; 254 unsigned long va;
248 struct vm_area_struct *vma; 255 struct vm_area_struct *vma;
256 int index;
249 /* A tristate: 257 /* A tristate:
250 * 0 for no errors 258 * 0 for no errors
251 * 1 if at least one error has happened (and no 259 * 1 if at least one error has happened (and no
@@ -260,14 +268,24 @@ struct mmap_batch_state {
260 xen_pfn_t __user *user_mfn; 268 xen_pfn_t __user *user_mfn;
261}; 269};
262 270
271/* auto translated dom0 note: if domU being created is PV, then mfn is
272 * mfn(addr on bus). If it's auto xlated, then mfn is pfn (input to HAP).
273 */
263static int mmap_batch_fn(void *data, void *state) 274static int mmap_batch_fn(void *data, void *state)
264{ 275{
265 xen_pfn_t *mfnp = data; 276 xen_pfn_t *mfnp = data;
266 struct mmap_batch_state *st = state; 277 struct mmap_batch_state *st = state;
278 struct vm_area_struct *vma = st->vma;
279 struct page **pages = vma->vm_private_data;
280 struct page *cur_page = NULL;
267 int ret; 281 int ret;
268 282
283 if (xen_feature(XENFEAT_auto_translated_physmap))
284 cur_page = pages[st->index++];
285
269 ret = xen_remap_domain_mfn_range(st->vma, st->va & PAGE_MASK, *mfnp, 1, 286 ret = xen_remap_domain_mfn_range(st->vma, st->va & PAGE_MASK, *mfnp, 1,
270 st->vma->vm_page_prot, st->domain); 287 st->vma->vm_page_prot, st->domain,
288 &cur_page);
271 289
272 /* Store error code for second pass. */ 290 /* Store error code for second pass. */
273 *(st->err++) = ret; 291 *(st->err++) = ret;
@@ -303,6 +321,32 @@ static int mmap_return_errors_v1(void *data, void *state)
303 return __put_user(*mfnp, st->user_mfn++); 321 return __put_user(*mfnp, st->user_mfn++);
304} 322}
305 323
324/* Allocate pfns that are then mapped with gmfns from foreign domid. Update
325 * the vma with the page info to use later.
326 * Returns: 0 if success, otherwise -errno
327 */
328static int alloc_empty_pages(struct vm_area_struct *vma, int numpgs)
329{
330 int rc;
331 struct page **pages;
332
333 pages = kcalloc(numpgs, sizeof(pages[0]), GFP_KERNEL);
334 if (pages == NULL)
335 return -ENOMEM;
336
337 rc = alloc_xenballooned_pages(numpgs, pages, 0);
338 if (rc != 0) {
339 pr_warn("%s Could not alloc %d pfns rc:%d\n", __func__,
340 numpgs, rc);
341 kfree(pages);
342 return -ENOMEM;
343 }
344 BUG_ON(vma->vm_private_data != PRIV_VMA_LOCKED);
345 vma->vm_private_data = pages;
346
347 return 0;
348}
349
306static struct vm_operations_struct privcmd_vm_ops; 350static struct vm_operations_struct privcmd_vm_ops;
307 351
308static long privcmd_ioctl_mmap_batch(void __user *udata, int version) 352static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
@@ -370,10 +414,18 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
370 ret = -EINVAL; 414 ret = -EINVAL;
371 goto out; 415 goto out;
372 } 416 }
417 if (xen_feature(XENFEAT_auto_translated_physmap)) {
418 ret = alloc_empty_pages(vma, m.num);
419 if (ret < 0) {
420 up_write(&mm->mmap_sem);
421 goto out;
422 }
423 }
373 424
374 state.domain = m.dom; 425 state.domain = m.dom;
375 state.vma = vma; 426 state.vma = vma;
376 state.va = m.addr; 427 state.va = m.addr;
428 state.index = 0;
377 state.global_error = 0; 429 state.global_error = 0;
378 state.err = err_array; 430 state.err = err_array;
379 431
@@ -442,6 +494,19 @@ static long privcmd_ioctl(struct file *file,
442 return ret; 494 return ret;
443} 495}
444 496
497static void privcmd_close(struct vm_area_struct *vma)
498{
499 struct page **pages = vma->vm_private_data;
500 int numpgs = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
501
502 if (!xen_feature(XENFEAT_auto_translated_physmap || !numpgs || !pages))
503 return;
504
505 xen_unmap_domain_mfn_range(vma, numpgs, pages);
506 free_xenballooned_pages(numpgs, pages);
507 kfree(pages);
508}
509
445static int privcmd_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 510static int privcmd_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
446{ 511{
447 printk(KERN_DEBUG "privcmd_fault: vma=%p %lx-%lx, pgoff=%lx, uv=%p\n", 512 printk(KERN_DEBUG "privcmd_fault: vma=%p %lx-%lx, pgoff=%lx, uv=%p\n",
@@ -452,6 +517,7 @@ static int privcmd_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
452} 517}
453 518
454static struct vm_operations_struct privcmd_vm_ops = { 519static struct vm_operations_struct privcmd_vm_ops = {
520 .close = privcmd_close,
455 .fault = privcmd_fault 521 .fault = privcmd_fault
456}; 522};
457 523
@@ -469,7 +535,7 @@ static int privcmd_mmap(struct file *file, struct vm_area_struct *vma)
469 535
470static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma) 536static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma)
471{ 537{
472 return (xchg(&vma->vm_private_data, (void *)1) == NULL); 538 return !cmpxchg(&vma->vm_private_data, NULL, PRIV_VMA_LOCKED);
473} 539}
474 540
475const struct file_operations xen_privcmd_fops = { 541const struct file_operations xen_privcmd_fops = {
diff --git a/drivers/xen/xen-acpi-pad.c b/drivers/xen/xen-acpi-pad.c
new file mode 100644
index 00000000000..da39191e727
--- /dev/null
+++ b/drivers/xen/xen-acpi-pad.c
@@ -0,0 +1,182 @@
1/*
2 * xen-acpi-pad.c - Xen pad interface
3 *
4 * Copyright (c) 2012, Intel Corporation.
5 * Author: Liu, Jinsong <jinsong.liu@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 */
16
17#include <linux/kernel.h>
18#include <linux/types.h>
19#include <acpi/acpi_bus.h>
20#include <acpi/acpi_drivers.h>
21#include <asm/xen/hypercall.h>
22#include <xen/interface/version.h>
23#include <xen/xen-ops.h>
24
25#define ACPI_PROCESSOR_AGGREGATOR_CLASS "acpi_pad"
26#define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator"
27#define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80
28static DEFINE_MUTEX(xen_cpu_lock);
29
30static int xen_acpi_pad_idle_cpus(unsigned int idle_nums)
31{
32 struct xen_platform_op op;
33
34 op.cmd = XENPF_core_parking;
35 op.u.core_parking.type = XEN_CORE_PARKING_SET;
36 op.u.core_parking.idle_nums = idle_nums;
37
38 return HYPERVISOR_dom0_op(&op);
39}
40
41static int xen_acpi_pad_idle_cpus_num(void)
42{
43 struct xen_platform_op op;
44
45 op.cmd = XENPF_core_parking;
46 op.u.core_parking.type = XEN_CORE_PARKING_GET;
47
48 return HYPERVISOR_dom0_op(&op)
49 ?: op.u.core_parking.idle_nums;
50}
51
52/*
53 * Query firmware how many CPUs should be idle
54 * return -1 on failure
55 */
56static int acpi_pad_pur(acpi_handle handle)
57{
58 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
59 union acpi_object *package;
60 int num = -1;
61
62 if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer)))
63 return num;
64
65 if (!buffer.length || !buffer.pointer)
66 return num;
67
68 package = buffer.pointer;
69
70 if (package->type == ACPI_TYPE_PACKAGE &&
71 package->package.count == 2 &&
72 package->package.elements[0].integer.value == 1) /* rev 1 */
73 num = package->package.elements[1].integer.value;
74
75 kfree(buffer.pointer);
76 return num;
77}
78
79/* Notify firmware how many CPUs are idle */
80static void acpi_pad_ost(acpi_handle handle, int stat,
81 uint32_t idle_nums)
82{
83 union acpi_object params[3] = {
84 {.type = ACPI_TYPE_INTEGER,},
85 {.type = ACPI_TYPE_INTEGER,},
86 {.type = ACPI_TYPE_BUFFER,},
87 };
88 struct acpi_object_list arg_list = {3, params};
89
90 params[0].integer.value = ACPI_PROCESSOR_AGGREGATOR_NOTIFY;
91 params[1].integer.value = stat;
92 params[2].buffer.length = 4;
93 params[2].buffer.pointer = (void *)&idle_nums;
94 acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
95}
96
97static void acpi_pad_handle_notify(acpi_handle handle)
98{
99 int idle_nums;
100
101 mutex_lock(&xen_cpu_lock);
102 idle_nums = acpi_pad_pur(handle);
103 if (idle_nums < 0) {
104 mutex_unlock(&xen_cpu_lock);
105 return;
106 }
107
108 idle_nums = xen_acpi_pad_idle_cpus(idle_nums)
109 ?: xen_acpi_pad_idle_cpus_num();
110 if (idle_nums >= 0)
111 acpi_pad_ost(handle, 0, idle_nums);
112 mutex_unlock(&xen_cpu_lock);
113}
114
115static void acpi_pad_notify(acpi_handle handle, u32 event,
116 void *data)
117{
118 switch (event) {
119 case ACPI_PROCESSOR_AGGREGATOR_NOTIFY:
120 acpi_pad_handle_notify(handle);
121 break;
122 default:
123 pr_warn("Unsupported event [0x%x]\n", event);
124 break;
125 }
126}
127
128static int acpi_pad_add(struct acpi_device *device)
129{
130 acpi_status status;
131
132 strcpy(acpi_device_name(device), ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME);
133 strcpy(acpi_device_class(device), ACPI_PROCESSOR_AGGREGATOR_CLASS);
134
135 status = acpi_install_notify_handler(device->handle,
136 ACPI_DEVICE_NOTIFY, acpi_pad_notify, device);
137 if (ACPI_FAILURE(status))
138 return -ENODEV;
139
140 return 0;
141}
142
143static int acpi_pad_remove(struct acpi_device *device,
144 int type)
145{
146 mutex_lock(&xen_cpu_lock);
147 xen_acpi_pad_idle_cpus(0);
148 mutex_unlock(&xen_cpu_lock);
149
150 acpi_remove_notify_handler(device->handle,
151 ACPI_DEVICE_NOTIFY, acpi_pad_notify);
152 return 0;
153}
154
155static const struct acpi_device_id pad_device_ids[] = {
156 {"ACPI000C", 0},
157 {"", 0},
158};
159
160static struct acpi_driver acpi_pad_driver = {
161 .name = "processor_aggregator",
162 .class = ACPI_PROCESSOR_AGGREGATOR_CLASS,
163 .ids = pad_device_ids,
164 .ops = {
165 .add = acpi_pad_add,
166 .remove = acpi_pad_remove,
167 },
168};
169
170static int __init xen_acpi_pad_init(void)
171{
172 /* Only DOM0 is responsible for Xen acpi pad */
173 if (!xen_initial_domain())
174 return -ENODEV;
175
176 /* Only Xen4.2 or later support Xen acpi pad */
177 if (!xen_running_on_version_or_later(4, 2))
178 return -ENODEV;
179
180 return acpi_bus_register_driver(&acpi_pad_driver);
181}
182subsys_initcall(xen_acpi_pad_init);
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 68dcc59cd28..cd50d251998 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -142,7 +142,8 @@ static struct pcistub_device *pcistub_device_find(int domain, int bus,
142 if (psdev->dev != NULL 142 if (psdev->dev != NULL
143 && domain == pci_domain_nr(psdev->dev->bus) 143 && domain == pci_domain_nr(psdev->dev->bus)
144 && bus == psdev->dev->bus->number 144 && bus == psdev->dev->bus->number
145 && PCI_DEVFN(slot, func) == psdev->dev->devfn) { 145 && slot == PCI_SLOT(psdev->dev->devfn)
146 && func == PCI_FUNC(psdev->dev->devfn)) {
146 pcistub_device_get(psdev); 147 pcistub_device_get(psdev);
147 goto out; 148 goto out;
148 } 149 }
@@ -191,7 +192,8 @@ struct pci_dev *pcistub_get_pci_dev_by_slot(struct xen_pcibk_device *pdev,
191 if (psdev->dev != NULL 192 if (psdev->dev != NULL
192 && domain == pci_domain_nr(psdev->dev->bus) 193 && domain == pci_domain_nr(psdev->dev->bus)
193 && bus == psdev->dev->bus->number 194 && bus == psdev->dev->bus->number
194 && PCI_DEVFN(slot, func) == psdev->dev->devfn) { 195 && slot == PCI_SLOT(psdev->dev->devfn)
196 && func == PCI_FUNC(psdev->dev->devfn)) {
195 found_dev = pcistub_device_get_pci_dev(pdev, psdev); 197 found_dev = pcistub_device_get_pci_dev(pdev, psdev);
196 break; 198 break;
197 } 199 }
@@ -897,42 +899,35 @@ static struct pci_driver xen_pcibk_pci_driver = {
897static inline int str_to_slot(const char *buf, int *domain, int *bus, 899static inline int str_to_slot(const char *buf, int *domain, int *bus,
898 int *slot, int *func) 900 int *slot, int *func)
899{ 901{
900 int err; 902 int parsed = 0;
901 char wc = '*';
902 903
903 err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func); 904 switch (sscanf(buf, " %x:%x:%x.%x %n", domain, bus, slot, func,
904 switch (err) { 905 &parsed)) {
905 case 3: 906 case 3:
906 *func = -1; 907 *func = -1;
907 err = sscanf(buf, " %x:%x:%x.%c", domain, bus, slot, &wc); 908 sscanf(buf, " %x:%x:%x.* %n", domain, bus, slot, &parsed);
908 break; 909 break;
909 case 2: 910 case 2:
910 *slot = *func = -1; 911 *slot = *func = -1;
911 err = sscanf(buf, " %x:%x:*.%c", domain, bus, &wc); 912 sscanf(buf, " %x:%x:*.* %n", domain, bus, &parsed);
912 if (err >= 2)
913 ++err;
914 break; 913 break;
915 } 914 }
916 if (err == 4 && wc == '*') 915 if (parsed && !buf[parsed])
917 return 0; 916 return 0;
918 else if (err < 0)
919 return -EINVAL;
920 917
921 /* try again without domain */ 918 /* try again without domain */
922 *domain = 0; 919 *domain = 0;
923 wc = '*'; 920 switch (sscanf(buf, " %x:%x.%x %n", bus, slot, func, &parsed)) {
924 err = sscanf(buf, " %x:%x.%x", bus, slot, func);
925 switch (err) {
926 case 2: 921 case 2:
927 *func = -1; 922 *func = -1;
928 err = sscanf(buf, " %x:%x.%c", bus, slot, &wc); 923 sscanf(buf, " %x:%x.* %n", bus, slot, &parsed);
929 break; 924 break;
930 case 1: 925 case 1:
931 *slot = *func = -1; 926 *slot = *func = -1;
932 err = sscanf(buf, " %x:*.%c", bus, &wc) + 1; 927 sscanf(buf, " %x:*.* %n", bus, &parsed);
933 break; 928 break;
934 } 929 }
935 if (err == 3 && wc == '*') 930 if (parsed && !buf[parsed])
936 return 0; 931 return 0;
937 932
938 return -EINVAL; 933 return -EINVAL;
@@ -941,13 +936,20 @@ static inline int str_to_slot(const char *buf, int *domain, int *bus,
941static inline int str_to_quirk(const char *buf, int *domain, int *bus, int 936static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
942 *slot, int *func, int *reg, int *size, int *mask) 937 *slot, int *func, int *reg, int *size, int *mask)
943{ 938{
944 int err; 939 int parsed = 0;
945 940
946 err = 941 sscanf(buf, " %x:%x:%x.%x-%x:%x:%x %n", domain, bus, slot, func,
947 sscanf(buf, " %04x:%02x:%02x.%d-%08x:%1x:%08x", domain, bus, slot, 942 reg, size, mask, &parsed);
948 func, reg, size, mask); 943 if (parsed && !buf[parsed])
949 if (err == 7)
950 return 0; 944 return 0;
945
946 /* try again without domain */
947 *domain = 0;
948 sscanf(buf, " %x:%x.%x-%x:%x:%x %n", bus, slot, func, reg, size,
949 mask, &parsed);
950 if (parsed && !buf[parsed])
951 return 0;
952
951 return -EINVAL; 953 return -EINVAL;
952} 954}
953 955
@@ -955,7 +957,7 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
955{ 957{
956 struct pcistub_device_id *pci_dev_id; 958 struct pcistub_device_id *pci_dev_id;
957 unsigned long flags; 959 unsigned long flags;
958 int rc = 0; 960 int rc = 0, devfn = PCI_DEVFN(slot, func);
959 961
960 if (slot < 0) { 962 if (slot < 0) {
961 for (slot = 0; !rc && slot < 32; ++slot) 963 for (slot = 0; !rc && slot < 32; ++slot)
@@ -969,13 +971,24 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
969 return rc; 971 return rc;
970 } 972 }
971 973
974 if ((
975#if !defined(MODULE) /* pci_domains_supported is not being exported */ \
976 || !defined(CONFIG_PCI_DOMAINS)
977 !pci_domains_supported ? domain :
978#endif
979 domain < 0 || domain > 0xffff)
980 || bus < 0 || bus > 0xff
981 || PCI_SLOT(devfn) != slot
982 || PCI_FUNC(devfn) != func)
983 return -EINVAL;
984
972 pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL); 985 pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
973 if (!pci_dev_id) 986 if (!pci_dev_id)
974 return -ENOMEM; 987 return -ENOMEM;
975 988
976 pci_dev_id->domain = domain; 989 pci_dev_id->domain = domain;
977 pci_dev_id->bus = bus; 990 pci_dev_id->bus = bus;
978 pci_dev_id->devfn = PCI_DEVFN(slot, func); 991 pci_dev_id->devfn = devfn;
979 992
980 pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%d\n", 993 pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%d\n",
981 domain, bus, slot, func); 994 domain, bus, slot, func);
@@ -1016,14 +1029,18 @@ static int pcistub_device_id_remove(int domain, int bus, int slot, int func)
1016 return err; 1029 return err;
1017} 1030}
1018 1031
1019static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg, 1032static int pcistub_reg_add(int domain, int bus, int slot, int func,
1020 int size, int mask) 1033 unsigned int reg, unsigned int size,
1034 unsigned int mask)
1021{ 1035{
1022 int err = 0; 1036 int err = 0;
1023 struct pcistub_device *psdev; 1037 struct pcistub_device *psdev;
1024 struct pci_dev *dev; 1038 struct pci_dev *dev;
1025 struct config_field *field; 1039 struct config_field *field;
1026 1040
1041 if (reg > 0xfff || (size < 4 && (mask >> (size * 8))))
1042 return -EINVAL;
1043
1027 psdev = pcistub_device_find(domain, bus, slot, func); 1044 psdev = pcistub_device_find(domain, bus, slot, func);
1028 if (!psdev) { 1045 if (!psdev) {
1029 err = -ENODEV; 1046 err = -ENODEV;
@@ -1254,13 +1271,11 @@ static ssize_t permissive_add(struct device_driver *drv, const char *buf,
1254 int err; 1271 int err;
1255 struct pcistub_device *psdev; 1272 struct pcistub_device *psdev;
1256 struct xen_pcibk_dev_data *dev_data; 1273 struct xen_pcibk_dev_data *dev_data;
1274
1257 err = str_to_slot(buf, &domain, &bus, &slot, &func); 1275 err = str_to_slot(buf, &domain, &bus, &slot, &func);
1258 if (err) 1276 if (err)
1259 goto out; 1277 goto out;
1260 if (slot < 0 || func < 0) { 1278
1261 err = -EINVAL;
1262 goto out;
1263 }
1264 psdev = pcistub_device_find(domain, bus, slot, func); 1279 psdev = pcistub_device_find(domain, bus, slot, func);
1265 if (!psdev) { 1280 if (!psdev) {
1266 err = -ENODEV; 1281 err = -ENODEV;
@@ -1339,8 +1354,6 @@ static int __init pcistub_init(void)
1339 1354
1340 if (pci_devs_to_hide && *pci_devs_to_hide) { 1355 if (pci_devs_to_hide && *pci_devs_to_hide) {
1341 do { 1356 do {
1342 char wc = '*';
1343
1344 parsed = 0; 1357 parsed = 0;
1345 1358
1346 err = sscanf(pci_devs_to_hide + pos, 1359 err = sscanf(pci_devs_to_hide + pos,
@@ -1349,51 +1362,48 @@ static int __init pcistub_init(void)
1349 switch (err) { 1362 switch (err) {
1350 case 3: 1363 case 3:
1351 func = -1; 1364 func = -1;
1352 err = sscanf(pci_devs_to_hide + pos, 1365 sscanf(pci_devs_to_hide + pos,
1353 " (%x:%x:%x.%c) %n", 1366 " (%x:%x:%x.*) %n",
1354 &domain, &bus, &slot, &wc, 1367 &domain, &bus, &slot, &parsed);
1355 &parsed);
1356 break; 1368 break;
1357 case 2: 1369 case 2:
1358 slot = func = -1; 1370 slot = func = -1;
1359 err = sscanf(pci_devs_to_hide + pos, 1371 sscanf(pci_devs_to_hide + pos,
1360 " (%x:%x:*.%c) %n", 1372 " (%x:%x:*.*) %n",
1361 &domain, &bus, &wc, &parsed) + 1; 1373 &domain, &bus, &parsed);
1362 break; 1374 break;
1363 } 1375 }
1364 1376
1365 if (err != 4 || wc != '*') { 1377 if (!parsed) {
1366 domain = 0; 1378 domain = 0;
1367 wc = '*';
1368 err = sscanf(pci_devs_to_hide + pos, 1379 err = sscanf(pci_devs_to_hide + pos,
1369 " (%x:%x.%x) %n", 1380 " (%x:%x.%x) %n",
1370 &bus, &slot, &func, &parsed); 1381 &bus, &slot, &func, &parsed);
1371 switch (err) { 1382 switch (err) {
1372 case 2: 1383 case 2:
1373 func = -1; 1384 func = -1;
1374 err = sscanf(pci_devs_to_hide + pos, 1385 sscanf(pci_devs_to_hide + pos,
1375 " (%x:%x.%c) %n", 1386 " (%x:%x.*) %n",
1376 &bus, &slot, &wc, 1387 &bus, &slot, &parsed);
1377 &parsed);
1378 break; 1388 break;
1379 case 1: 1389 case 1:
1380 slot = func = -1; 1390 slot = func = -1;
1381 err = sscanf(pci_devs_to_hide + pos, 1391 sscanf(pci_devs_to_hide + pos,
1382 " (%x:*.%c) %n", 1392 " (%x:*.*) %n",
1383 &bus, &wc, &parsed) + 1; 1393 &bus, &parsed);
1384 break; 1394 break;
1385 } 1395 }
1386 if (err != 3 || wc != '*')
1387 goto parse_error;
1388 } 1396 }
1389 1397
1398 if (parsed <= 0)
1399 goto parse_error;
1400
1390 err = pcistub_device_id_add(domain, bus, slot, func); 1401 err = pcistub_device_id_add(domain, bus, slot, func);
1391 if (err) 1402 if (err)
1392 goto out; 1403 goto out;
1393 1404
1394 /* if parsed<=0, we've reached the end of the string */
1395 pos += parsed; 1405 pos += parsed;
1396 } while (parsed > 0 && pci_devs_to_hide[pos]); 1406 } while (pci_devs_to_hide[pos]);
1397 } 1407 }
1398 1408
1399 /* If we're the first PCI Device Driver to register, we're the 1409 /* If we're the first PCI Device Driver to register, we're the
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index acedeabe589..88e677b0de7 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -48,7 +48,6 @@
48#include <xen/xenbus.h> 48#include <xen/xenbus.h>
49#include <xen/xen.h> 49#include <xen/xen.h>
50#include "xenbus_comms.h" 50#include "xenbus_comms.h"
51#include <asm/xen/hypervisor.h>
52 51
53struct xs_stored_msg { 52struct xs_stored_msg {
54 struct list_head list; 53 struct list_head list;