diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 17:29:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 17:29:16 -0500 |
commit | 896ea17d3da5f44b2625c9cda9874d7dfe447393 (patch) | |
tree | 089f00dd300a49c81f042e9b52ef32cd1333bdbc /drivers/xen | |
parent | c7708fac5a878d6e0f2de0aa19f9749cff4f707f (diff) | |
parent | 6a7ed405114b2a53ccd99631b0636aaeabf71b3e (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/Kconfig | 3 | ||||
-rw-r--r-- | drivers/xen/Makefile | 7 | ||||
-rw-r--r-- | drivers/xen/balloon.c | 5 | ||||
-rw-r--r-- | drivers/xen/privcmd.c | 72 | ||||
-rw-r--r-- | drivers/xen/xen-acpi-pad.c | 182 | ||||
-rw-r--r-- | drivers/xen/xen-pciback/pci_stub.c | 118 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_xs.c | 1 |
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 | ||
209 | config XEN_HAVE_PVMMU | ||
210 | bool | ||
211 | |||
209 | endmenu | 212 | endmenu |
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 @@ | |||
1 | ifneq ($(CONFIG_ARM),y) | 1 | ifneq ($(CONFIG_ARM),y) |
2 | obj-y += manage.o balloon.o | 2 | obj-y += manage.o |
3 | obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o | 3 | obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o |
4 | endif | 4 | endif |
5 | obj-$(CONFIG_X86) += fallback.o | 5 | obj-$(CONFIG_X86) += fallback.o |
6 | obj-y += grant-table.o features.o events.o | 6 | obj-y += grant-table.o features.o events.o balloon.o |
7 | obj-y += xenbus/ | 7 | obj-y += xenbus/ |
8 | 8 | ||
9 | nostackp := $(call cc-option, -fno-stack-protector) | 9 | nostackp := $(call cc-option, -fno-stack-protector) |
@@ -11,7 +11,8 @@ CFLAGS_features.o := $(nostackp) | |||
11 | 11 | ||
12 | dom0-$(CONFIG_PCI) += pci.o | 12 | dom0-$(CONFIG_PCI) += pci.o |
13 | dom0-$(CONFIG_USB_SUPPORT) += dbgp.o | 13 | dom0-$(CONFIG_USB_SUPPORT) += dbgp.o |
14 | dom0-$(CONFIG_ACPI) += acpi.o | 14 | dom0-$(CONFIG_ACPI) += acpi.o $(xen-pad-y) |
15 | xen-pad-$(CONFIG_X86) += xen-acpi-pad.o | ||
15 | dom0-$(CONFIG_X86) += pcpu.o | 16 | dom0-$(CONFIG_X86) += pcpu.o |
16 | obj-$(CONFIG_XEN_DOM0) += $(dom0-y) | 17 | obj-$(CONFIG_XEN_DOM0) += $(dom0-y) |
17 | obj-$(CONFIG_BLOCK) += biomerge.o | 18 | obj-$(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 | ||
39 | MODULE_LICENSE("GPL"); | 40 | MODULE_LICENSE("GPL"); |
40 | 41 | ||
42 | #define PRIV_VMA_LOCKED ((void *)1) | ||
43 | |||
41 | #ifndef HAVE_ARCH_PRIVCMD_MMAP | 44 | #ifndef HAVE_ARCH_PRIVCMD_MMAP |
42 | static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma); | 45 | static 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 | */ | ||
263 | static int mmap_batch_fn(void *data, void *state) | 274 | static 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 | */ | ||
328 | static 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 | |||
306 | static struct vm_operations_struct privcmd_vm_ops; | 350 | static struct vm_operations_struct privcmd_vm_ops; |
307 | 351 | ||
308 | static long privcmd_ioctl_mmap_batch(void __user *udata, int version) | 352 | static 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 | ||
497 | static 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 | |||
445 | static int privcmd_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | 510 | static 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 | ||
454 | static struct vm_operations_struct privcmd_vm_ops = { | 519 | static 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 | ||
470 | static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma) | 536 | static 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 | ||
475 | const struct file_operations xen_privcmd_fops = { | 541 | const 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 | ||
28 | static DEFINE_MUTEX(xen_cpu_lock); | ||
29 | |||
30 | static 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 | |||
41 | static 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 | */ | ||
56 | static 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 */ | ||
80 | static 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 | |||
97 | static 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 | |||
115 | static 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 | |||
128 | static 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 | |||
143 | static 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 | |||
155 | static const struct acpi_device_id pad_device_ids[] = { | ||
156 | {"ACPI000C", 0}, | ||
157 | {"", 0}, | ||
158 | }; | ||
159 | |||
160 | static 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 | |||
170 | static 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 | } | ||
182 | subsys_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 = { | |||
897 | static inline int str_to_slot(const char *buf, int *domain, int *bus, | 899 | static 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, | |||
941 | static inline int str_to_quirk(const char *buf, int *domain, int *bus, int | 936 | static 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 | ||
1019 | static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg, | 1032 | static 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 | ||
53 | struct xs_stored_msg { | 52 | struct xs_stored_msg { |
54 | struct list_head list; | 53 | struct list_head list; |