diff options
-rw-r--r-- | arch/arm/include/asm/xen/interface.h | 1 | ||||
-rw-r--r-- | arch/arm/xen/enlighten.c | 123 | ||||
-rw-r--r-- | arch/x86/include/asm/xen/interface.h | 1 | ||||
-rw-r--r-- | arch/x86/xen/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 102 | ||||
-rw-r--r-- | arch/x86/xen/mmu.c | 17 | ||||
-rw-r--r-- | arch/x86/xen/suspend.c | 2 | ||||
-rw-r--r-- | arch/x86/xen/xen-ops.h | 2 | ||||
-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 | ||||
-rw-r--r-- | include/xen/interface/memory.h | 44 | ||||
-rw-r--r-- | include/xen/interface/platform.h | 17 | ||||
-rw-r--r-- | include/xen/xen-ops.h | 9 |
18 files changed, 591 insertions, 116 deletions
diff --git a/arch/arm/include/asm/xen/interface.h b/arch/arm/include/asm/xen/interface.h index 5000397134b4..1151188bcd83 100644 --- a/arch/arm/include/asm/xen/interface.h +++ b/arch/arm/include/asm/xen/interface.h | |||
@@ -49,6 +49,7 @@ DEFINE_GUEST_HANDLE(void); | |||
49 | DEFINE_GUEST_HANDLE(uint64_t); | 49 | DEFINE_GUEST_HANDLE(uint64_t); |
50 | DEFINE_GUEST_HANDLE(uint32_t); | 50 | DEFINE_GUEST_HANDLE(uint32_t); |
51 | DEFINE_GUEST_HANDLE(xen_pfn_t); | 51 | DEFINE_GUEST_HANDLE(xen_pfn_t); |
52 | DEFINE_GUEST_HANDLE(xen_ulong_t); | ||
52 | 53 | ||
53 | /* Maximum number of virtual CPUs in multi-processor guests. */ | 54 | /* Maximum number of virtual CPUs in multi-processor guests. */ |
54 | #define MAX_VIRT_CPUS 1 | 55 | #define MAX_VIRT_CPUS 1 |
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index f57609275449..7a32976fa2a3 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c | |||
@@ -8,6 +8,8 @@ | |||
8 | #include <xen/features.h> | 8 | #include <xen/features.h> |
9 | #include <xen/platform_pci.h> | 9 | #include <xen/platform_pci.h> |
10 | #include <xen/xenbus.h> | 10 | #include <xen/xenbus.h> |
11 | #include <xen/page.h> | ||
12 | #include <xen/xen-ops.h> | ||
11 | #include <asm/xen/hypervisor.h> | 13 | #include <asm/xen/hypervisor.h> |
12 | #include <asm/xen/hypercall.h> | 14 | #include <asm/xen/hypercall.h> |
13 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
@@ -17,6 +19,8 @@ | |||
17 | #include <linux/of_irq.h> | 19 | #include <linux/of_irq.h> |
18 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
19 | 21 | ||
22 | #include <linux/mm.h> | ||
23 | |||
20 | struct start_info _xen_start_info; | 24 | struct start_info _xen_start_info; |
21 | struct start_info *xen_start_info = &_xen_start_info; | 25 | struct start_info *xen_start_info = &_xen_start_info; |
22 | EXPORT_SYMBOL_GPL(xen_start_info); | 26 | EXPORT_SYMBOL_GPL(xen_start_info); |
@@ -29,6 +33,10 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; | |||
29 | 33 | ||
30 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); | 34 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); |
31 | 35 | ||
36 | /* These are unused until we support booting "pre-ballooned" */ | ||
37 | unsigned long xen_released_pages; | ||
38 | struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata; | ||
39 | |||
32 | /* TODO: to be removed */ | 40 | /* TODO: to be removed */ |
33 | __read_mostly int xen_have_vector_callback; | 41 | __read_mostly int xen_have_vector_callback; |
34 | EXPORT_SYMBOL_GPL(xen_have_vector_callback); | 42 | EXPORT_SYMBOL_GPL(xen_have_vector_callback); |
@@ -38,15 +46,106 @@ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug); | |||
38 | 46 | ||
39 | static __read_mostly int xen_events_irq = -1; | 47 | static __read_mostly int xen_events_irq = -1; |
40 | 48 | ||
49 | /* map fgmfn of domid to lpfn in the current domain */ | ||
50 | static int map_foreign_page(unsigned long lpfn, unsigned long fgmfn, | ||
51 | unsigned int domid) | ||
52 | { | ||
53 | int rc; | ||
54 | struct xen_add_to_physmap_range xatp = { | ||
55 | .domid = DOMID_SELF, | ||
56 | .foreign_domid = domid, | ||
57 | .size = 1, | ||
58 | .space = XENMAPSPACE_gmfn_foreign, | ||
59 | }; | ||
60 | xen_ulong_t idx = fgmfn; | ||
61 | xen_pfn_t gpfn = lpfn; | ||
62 | |||
63 | set_xen_guest_handle(xatp.idxs, &idx); | ||
64 | set_xen_guest_handle(xatp.gpfns, &gpfn); | ||
65 | |||
66 | rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp); | ||
67 | if (rc) { | ||
68 | pr_warn("Failed to map pfn to mfn rc:%d pfn:%lx mfn:%lx\n", | ||
69 | rc, lpfn, fgmfn); | ||
70 | return 1; | ||
71 | } | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | struct remap_data { | ||
76 | xen_pfn_t fgmfn; /* foreign domain's gmfn */ | ||
77 | pgprot_t prot; | ||
78 | domid_t domid; | ||
79 | struct vm_area_struct *vma; | ||
80 | int index; | ||
81 | struct page **pages; | ||
82 | struct xen_remap_mfn_info *info; | ||
83 | }; | ||
84 | |||
85 | static int remap_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr, | ||
86 | void *data) | ||
87 | { | ||
88 | struct remap_data *info = data; | ||
89 | struct page *page = info->pages[info->index++]; | ||
90 | unsigned long pfn = page_to_pfn(page); | ||
91 | pte_t pte = pfn_pte(pfn, info->prot); | ||
92 | |||
93 | if (map_foreign_page(pfn, info->fgmfn, info->domid)) | ||
94 | return -EFAULT; | ||
95 | set_pte_at(info->vma->vm_mm, addr, ptep, pte); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
41 | int xen_remap_domain_mfn_range(struct vm_area_struct *vma, | 100 | int xen_remap_domain_mfn_range(struct vm_area_struct *vma, |
42 | unsigned long addr, | 101 | unsigned long addr, |
43 | unsigned long mfn, int nr, | 102 | xen_pfn_t mfn, int nr, |
44 | pgprot_t prot, unsigned domid) | 103 | pgprot_t prot, unsigned domid, |
104 | struct page **pages) | ||
45 | { | 105 | { |
46 | return -ENOSYS; | 106 | int err; |
107 | struct remap_data data; | ||
108 | |||
109 | /* TBD: Batching, current sole caller only does page at a time */ | ||
110 | if (nr > 1) | ||
111 | return -EINVAL; | ||
112 | |||
113 | data.fgmfn = mfn; | ||
114 | data.prot = prot; | ||
115 | data.domid = domid; | ||
116 | data.vma = vma; | ||
117 | data.index = 0; | ||
118 | data.pages = pages; | ||
119 | err = apply_to_page_range(vma->vm_mm, addr, nr << PAGE_SHIFT, | ||
120 | remap_pte_fn, &data); | ||
121 | return err; | ||
47 | } | 122 | } |
48 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); | 123 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); |
49 | 124 | ||
125 | int xen_unmap_domain_mfn_range(struct vm_area_struct *vma, | ||
126 | int nr, struct page **pages) | ||
127 | { | ||
128 | int i; | ||
129 | |||
130 | for (i = 0; i < nr; i++) { | ||
131 | struct xen_remove_from_physmap xrp; | ||
132 | unsigned long rc, pfn; | ||
133 | |||
134 | pfn = page_to_pfn(pages[i]); | ||
135 | |||
136 | xrp.domid = DOMID_SELF; | ||
137 | xrp.gpfn = pfn; | ||
138 | rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp); | ||
139 | if (rc) { | ||
140 | pr_warn("Failed to unmap pfn:%lx rc:%ld\n", | ||
141 | pfn, rc); | ||
142 | return rc; | ||
143 | } | ||
144 | } | ||
145 | return 0; | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range); | ||
148 | |||
50 | /* | 149 | /* |
51 | * see Documentation/devicetree/bindings/arm/xen.txt for the | 150 | * see Documentation/devicetree/bindings/arm/xen.txt for the |
52 | * documentation of the Xen Device Tree format. | 151 | * documentation of the Xen Device Tree format. |
@@ -149,24 +248,6 @@ static int __init xen_init_events(void) | |||
149 | } | 248 | } |
150 | postcore_initcall(xen_init_events); | 249 | postcore_initcall(xen_init_events); |
151 | 250 | ||
152 | /* XXX: only until balloon is properly working */ | ||
153 | int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem) | ||
154 | { | ||
155 | *pages = alloc_pages(highmem ? GFP_HIGHUSER : GFP_KERNEL, | ||
156 | get_order(nr_pages)); | ||
157 | if (*pages == NULL) | ||
158 | return -ENOMEM; | ||
159 | return 0; | ||
160 | } | ||
161 | EXPORT_SYMBOL_GPL(alloc_xenballooned_pages); | ||
162 | |||
163 | void free_xenballooned_pages(int nr_pages, struct page **pages) | ||
164 | { | ||
165 | kfree(*pages); | ||
166 | *pages = NULL; | ||
167 | } | ||
168 | EXPORT_SYMBOL_GPL(free_xenballooned_pages); | ||
169 | |||
170 | /* In the hypervisor.S file. */ | 251 | /* In the hypervisor.S file. */ |
171 | EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op); | 252 | EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op); |
172 | EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op); | 253 | EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op); |
diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h index 54d52ff1304a..fd9cb7695b5f 100644 --- a/arch/x86/include/asm/xen/interface.h +++ b/arch/x86/include/asm/xen/interface.h | |||
@@ -63,6 +63,7 @@ DEFINE_GUEST_HANDLE(void); | |||
63 | DEFINE_GUEST_HANDLE(uint64_t); | 63 | DEFINE_GUEST_HANDLE(uint64_t); |
64 | DEFINE_GUEST_HANDLE(uint32_t); | 64 | DEFINE_GUEST_HANDLE(uint32_t); |
65 | DEFINE_GUEST_HANDLE(xen_pfn_t); | 65 | DEFINE_GUEST_HANDLE(xen_pfn_t); |
66 | DEFINE_GUEST_HANDLE(xen_ulong_t); | ||
66 | #endif | 67 | #endif |
67 | 68 | ||
68 | #ifndef HYPERVISOR_VIRT_START | 69 | #ifndef HYPERVISOR_VIRT_START |
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig index 9a6775c9ddca..131dacd2748a 100644 --- a/arch/x86/xen/Kconfig +++ b/arch/x86/xen/Kconfig | |||
@@ -6,6 +6,7 @@ config XEN | |||
6 | bool "Xen guest support" | 6 | bool "Xen guest support" |
7 | select PARAVIRT | 7 | select PARAVIRT |
8 | select PARAVIRT_CLOCK | 8 | select PARAVIRT_CLOCK |
9 | select XEN_HAVE_PVMMU | ||
9 | depends on X86_64 || (X86_32 && X86_PAE && !X86_VISWS) | 10 | depends on X86_64 || (X86_32 && X86_PAE && !X86_VISWS) |
10 | depends on X86_TSC | 11 | depends on X86_TSC |
11 | help | 12 | help |
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 586d83812b67..3aeaa933b527 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -223,6 +223,21 @@ static void __init xen_banner(void) | |||
223 | version >> 16, version & 0xffff, extra.extraversion, | 223 | version >> 16, version & 0xffff, extra.extraversion, |
224 | xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); | 224 | xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); |
225 | } | 225 | } |
226 | /* Check if running on Xen version (major, minor) or later */ | ||
227 | bool | ||
228 | xen_running_on_version_or_later(unsigned int major, unsigned int minor) | ||
229 | { | ||
230 | unsigned int version; | ||
231 | |||
232 | if (!xen_domain()) | ||
233 | return false; | ||
234 | |||
235 | version = HYPERVISOR_xen_version(XENVER_version, NULL); | ||
236 | if ((((version >> 16) == major) && ((version & 0xffff) >= minor)) || | ||
237 | ((version >> 16) > major)) | ||
238 | return true; | ||
239 | return false; | ||
240 | } | ||
226 | 241 | ||
227 | #define CPUID_THERM_POWER_LEAF 6 | 242 | #define CPUID_THERM_POWER_LEAF 6 |
228 | #define APERFMPERF_PRESENT 0 | 243 | #define APERFMPERF_PRESENT 0 |
@@ -287,8 +302,7 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx, | |||
287 | 302 | ||
288 | static bool __init xen_check_mwait(void) | 303 | static bool __init xen_check_mwait(void) |
289 | { | 304 | { |
290 | #if defined(CONFIG_ACPI) && !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) && \ | 305 | #ifdef CONFIG_ACPI |
291 | !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) | ||
292 | struct xen_platform_op op = { | 306 | struct xen_platform_op op = { |
293 | .cmd = XENPF_set_processor_pminfo, | 307 | .cmd = XENPF_set_processor_pminfo, |
294 | .u.set_pminfo.id = -1, | 308 | .u.set_pminfo.id = -1, |
@@ -309,6 +323,13 @@ static bool __init xen_check_mwait(void) | |||
309 | if (!xen_initial_domain()) | 323 | if (!xen_initial_domain()) |
310 | return false; | 324 | return false; |
311 | 325 | ||
326 | /* | ||
327 | * When running under platform earlier than Xen4.2, do not expose | ||
328 | * mwait, to avoid the risk of loading native acpi pad driver | ||
329 | */ | ||
330 | if (!xen_running_on_version_or_later(4, 2)) | ||
331 | return false; | ||
332 | |||
312 | ax = 1; | 333 | ax = 1; |
313 | cx = 0; | 334 | cx = 0; |
314 | 335 | ||
@@ -1495,51 +1516,72 @@ asmlinkage void __init xen_start_kernel(void) | |||
1495 | #endif | 1516 | #endif |
1496 | } | 1517 | } |
1497 | 1518 | ||
1498 | void __ref xen_hvm_init_shared_info(void) | 1519 | #ifdef CONFIG_XEN_PVHVM |
1520 | #define HVM_SHARED_INFO_ADDR 0xFE700000UL | ||
1521 | static struct shared_info *xen_hvm_shared_info; | ||
1522 | static unsigned long xen_hvm_sip_phys; | ||
1523 | static int xen_major, xen_minor; | ||
1524 | |||
1525 | static void xen_hvm_connect_shared_info(unsigned long pfn) | ||
1499 | { | 1526 | { |
1500 | int cpu; | ||
1501 | struct xen_add_to_physmap xatp; | 1527 | struct xen_add_to_physmap xatp; |
1502 | static struct shared_info *shared_info_page = 0; | ||
1503 | 1528 | ||
1504 | if (!shared_info_page) | ||
1505 | shared_info_page = (struct shared_info *) | ||
1506 | extend_brk(PAGE_SIZE, PAGE_SIZE); | ||
1507 | xatp.domid = DOMID_SELF; | 1529 | xatp.domid = DOMID_SELF; |
1508 | xatp.idx = 0; | 1530 | xatp.idx = 0; |
1509 | xatp.space = XENMAPSPACE_shared_info; | 1531 | xatp.space = XENMAPSPACE_shared_info; |
1510 | xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT; | 1532 | xatp.gpfn = pfn; |
1511 | if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) | 1533 | if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) |
1512 | BUG(); | 1534 | BUG(); |
1513 | 1535 | ||
1514 | HYPERVISOR_shared_info = (struct shared_info *)shared_info_page; | 1536 | } |
1537 | static void __init xen_hvm_set_shared_info(struct shared_info *sip) | ||
1538 | { | ||
1539 | int cpu; | ||
1540 | |||
1541 | HYPERVISOR_shared_info = sip; | ||
1515 | 1542 | ||
1516 | /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info | 1543 | /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info |
1517 | * page, we use it in the event channel upcall and in some pvclock | 1544 | * page, we use it in the event channel upcall and in some pvclock |
1518 | * related functions. We don't need the vcpu_info placement | 1545 | * related functions. We don't need the vcpu_info placement |
1519 | * optimizations because we don't use any pv_mmu or pv_irq op on | 1546 | * optimizations because we don't use any pv_mmu or pv_irq op on |
1520 | * HVM. | 1547 | * HVM. */ |
1521 | * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is | 1548 | for_each_online_cpu(cpu) |
1522 | * online but xen_hvm_init_shared_info is run at resume time too and | ||
1523 | * in that case multiple vcpus might be online. */ | ||
1524 | for_each_online_cpu(cpu) { | ||
1525 | per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; | 1549 | per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; |
1550 | } | ||
1551 | |||
1552 | /* Reconnect the shared_info pfn to a (new) mfn */ | ||
1553 | void xen_hvm_resume_shared_info(void) | ||
1554 | { | ||
1555 | xen_hvm_connect_shared_info(xen_hvm_sip_phys >> PAGE_SHIFT); | ||
1556 | } | ||
1557 | |||
1558 | /* Xen tools prior to Xen 4 do not provide a E820_Reserved area for guest usage. | ||
1559 | * On these old tools the shared info page will be placed in E820_Ram. | ||
1560 | * Xen 4 provides a E820_Reserved area at 0xFC000000, and this code expects | ||
1561 | * that nothing is mapped up to HVM_SHARED_INFO_ADDR. | ||
1562 | * Xen 4.3+ provides an explicit 1MB area at HVM_SHARED_INFO_ADDR which is used | ||
1563 | * here for the shared info page. */ | ||
1564 | static void __init xen_hvm_init_shared_info(void) | ||
1565 | { | ||
1566 | if (xen_major < 4) { | ||
1567 | xen_hvm_shared_info = extend_brk(PAGE_SIZE, PAGE_SIZE); | ||
1568 | xen_hvm_sip_phys = __pa(xen_hvm_shared_info); | ||
1569 | } else { | ||
1570 | xen_hvm_sip_phys = HVM_SHARED_INFO_ADDR; | ||
1571 | set_fixmap(FIX_PARAVIRT_BOOTMAP, xen_hvm_sip_phys); | ||
1572 | xen_hvm_shared_info = | ||
1573 | (struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP); | ||
1526 | } | 1574 | } |
1575 | xen_hvm_connect_shared_info(xen_hvm_sip_phys >> PAGE_SHIFT); | ||
1576 | xen_hvm_set_shared_info(xen_hvm_shared_info); | ||
1527 | } | 1577 | } |
1528 | 1578 | ||
1529 | #ifdef CONFIG_XEN_PVHVM | ||
1530 | static void __init init_hvm_pv_info(void) | 1579 | static void __init init_hvm_pv_info(void) |
1531 | { | 1580 | { |
1532 | int major, minor; | 1581 | uint32_t ecx, edx, pages, msr, base; |
1533 | uint32_t eax, ebx, ecx, edx, pages, msr, base; | ||
1534 | u64 pfn; | 1582 | u64 pfn; |
1535 | 1583 | ||
1536 | base = xen_cpuid_base(); | 1584 | base = xen_cpuid_base(); |
1537 | cpuid(base + 1, &eax, &ebx, &ecx, &edx); | ||
1538 | |||
1539 | major = eax >> 16; | ||
1540 | minor = eax & 0xffff; | ||
1541 | printk(KERN_INFO "Xen version %d.%d.\n", major, minor); | ||
1542 | |||
1543 | cpuid(base + 2, &pages, &msr, &ecx, &edx); | 1585 | cpuid(base + 2, &pages, &msr, &ecx, &edx); |
1544 | 1586 | ||
1545 | pfn = __pa(hypercall_page); | 1587 | pfn = __pa(hypercall_page); |
@@ -1590,12 +1632,22 @@ static void __init xen_hvm_guest_init(void) | |||
1590 | 1632 | ||
1591 | static bool __init xen_hvm_platform(void) | 1633 | static bool __init xen_hvm_platform(void) |
1592 | { | 1634 | { |
1635 | uint32_t eax, ebx, ecx, edx, base; | ||
1636 | |||
1593 | if (xen_pv_domain()) | 1637 | if (xen_pv_domain()) |
1594 | return false; | 1638 | return false; |
1595 | 1639 | ||
1596 | if (!xen_cpuid_base()) | 1640 | base = xen_cpuid_base(); |
1641 | if (!base) | ||
1597 | return false; | 1642 | return false; |
1598 | 1643 | ||
1644 | cpuid(base + 1, &eax, &ebx, &ecx, &edx); | ||
1645 | |||
1646 | xen_major = eax >> 16; | ||
1647 | xen_minor = eax & 0xffff; | ||
1648 | |||
1649 | printk(KERN_INFO "Xen version %d.%d.\n", xen_major, xen_minor); | ||
1650 | |||
1599 | return true; | 1651 | return true; |
1600 | } | 1652 | } |
1601 | 1653 | ||
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index dcf5f2dd91ec..01de35c77221 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -2497,8 +2497,10 @@ static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token, | |||
2497 | 2497 | ||
2498 | int xen_remap_domain_mfn_range(struct vm_area_struct *vma, | 2498 | int xen_remap_domain_mfn_range(struct vm_area_struct *vma, |
2499 | unsigned long addr, | 2499 | unsigned long addr, |
2500 | unsigned long mfn, int nr, | 2500 | xen_pfn_t mfn, int nr, |
2501 | pgprot_t prot, unsigned domid) | 2501 | pgprot_t prot, unsigned domid, |
2502 | struct page **pages) | ||
2503 | |||
2502 | { | 2504 | { |
2503 | struct remap_data rmd; | 2505 | struct remap_data rmd; |
2504 | struct mmu_update mmu_update[REMAP_BATCH_SIZE]; | 2506 | struct mmu_update mmu_update[REMAP_BATCH_SIZE]; |
@@ -2542,3 +2544,14 @@ out: | |||
2542 | return err; | 2544 | return err; |
2543 | } | 2545 | } |
2544 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); | 2546 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); |
2547 | |||
2548 | /* Returns: 0 success */ | ||
2549 | int xen_unmap_domain_mfn_range(struct vm_area_struct *vma, | ||
2550 | int numpgs, struct page **pages) | ||
2551 | { | ||
2552 | if (!pages || !xen_feature(XENFEAT_auto_translated_physmap)) | ||
2553 | return 0; | ||
2554 | |||
2555 | return -EINVAL; | ||
2556 | } | ||
2557 | EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range); | ||
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c index 45329c8c226e..ae8a00c39de4 100644 --- a/arch/x86/xen/suspend.c +++ b/arch/x86/xen/suspend.c | |||
@@ -30,7 +30,7 @@ void xen_arch_hvm_post_suspend(int suspend_cancelled) | |||
30 | { | 30 | { |
31 | #ifdef CONFIG_XEN_PVHVM | 31 | #ifdef CONFIG_XEN_PVHVM |
32 | int cpu; | 32 | int cpu; |
33 | xen_hvm_init_shared_info(); | 33 | xen_hvm_resume_shared_info(); |
34 | xen_callback_vector(); | 34 | xen_callback_vector(); |
35 | xen_unplug_emulated_devices(); | 35 | xen_unplug_emulated_devices(); |
36 | if (xen_feature(XENFEAT_hvm_safe_pvclock)) { | 36 | if (xen_feature(XENFEAT_hvm_safe_pvclock)) { |
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index a95b41744ad0..d2e73d19d366 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h | |||
@@ -40,7 +40,7 @@ void xen_enable_syscall(void); | |||
40 | void xen_vcpu_restore(void); | 40 | void xen_vcpu_restore(void); |
41 | 41 | ||
42 | void xen_callback_vector(void); | 42 | void xen_callback_vector(void); |
43 | void xen_hvm_init_shared_info(void); | 43 | void xen_hvm_resume_shared_info(void); |
44 | void xen_unplug_emulated_devices(void); | 44 | void xen_unplug_emulated_devices(void); |
45 | 45 | ||
46 | void __init xen_build_dynamic_phys_to_machine(void); | 46 | void __init xen_build_dynamic_phys_to_machine(void); |
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 126d8ce591ce..cabfa97f4674 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 74354708c6c4..fb213cf81a7b 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 d6886d90ccfd..a56776dbe095 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 71f5c459b088..0bbbccbb1f12 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 000000000000..da39191e7278 --- /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 68dcc59cd287..cd50d251998e 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 acedeabe589c..88e677b0de74 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; |
diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h index 90712e2072d5..b40a4315cb8b 100644 --- a/include/xen/interface/memory.h +++ b/include/xen/interface/memory.h | |||
@@ -153,6 +153,14 @@ struct xen_machphys_mapping { | |||
153 | }; | 153 | }; |
154 | DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mapping_t); | 154 | DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mapping_t); |
155 | 155 | ||
156 | #define XENMAPSPACE_shared_info 0 /* shared info page */ | ||
157 | #define XENMAPSPACE_grant_table 1 /* grant table page */ | ||
158 | #define XENMAPSPACE_gmfn 2 /* GMFN */ | ||
159 | #define XENMAPSPACE_gmfn_range 3 /* GMFN range, XENMEM_add_to_physmap only. */ | ||
160 | #define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom, | ||
161 | * XENMEM_add_to_physmap_range only. | ||
162 | */ | ||
163 | |||
156 | /* | 164 | /* |
157 | * Sets the GPFN at which a particular page appears in the specified guest's | 165 | * Sets the GPFN at which a particular page appears in the specified guest's |
158 | * pseudophysical address space. | 166 | * pseudophysical address space. |
@@ -167,8 +175,6 @@ struct xen_add_to_physmap { | |||
167 | uint16_t size; | 175 | uint16_t size; |
168 | 176 | ||
169 | /* Source mapping space. */ | 177 | /* Source mapping space. */ |
170 | #define XENMAPSPACE_shared_info 0 /* shared info page */ | ||
171 | #define XENMAPSPACE_grant_table 1 /* grant table page */ | ||
172 | unsigned int space; | 178 | unsigned int space; |
173 | 179 | ||
174 | /* Index into source mapping space. */ | 180 | /* Index into source mapping space. */ |
@@ -182,6 +188,24 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap); | |||
182 | /*** REMOVED ***/ | 188 | /*** REMOVED ***/ |
183 | /*#define XENMEM_translate_gpfn_list 8*/ | 189 | /*#define XENMEM_translate_gpfn_list 8*/ |
184 | 190 | ||
191 | #define XENMEM_add_to_physmap_range 23 | ||
192 | struct xen_add_to_physmap_range { | ||
193 | /* Which domain to change the mapping for. */ | ||
194 | domid_t domid; | ||
195 | uint16_t space; /* => enum phys_map_space */ | ||
196 | |||
197 | /* Number of pages to go through */ | ||
198 | uint16_t size; | ||
199 | domid_t foreign_domid; /* IFF gmfn_foreign */ | ||
200 | |||
201 | /* Indexes into space being mapped. */ | ||
202 | GUEST_HANDLE(xen_ulong_t) idxs; | ||
203 | |||
204 | /* GPFN in domid where the source mapping page should appear. */ | ||
205 | GUEST_HANDLE(xen_pfn_t) gpfns; | ||
206 | }; | ||
207 | DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap_range); | ||
208 | |||
185 | /* | 209 | /* |
186 | * Returns the pseudo-physical memory map as it was when the domain | 210 | * Returns the pseudo-physical memory map as it was when the domain |
187 | * was started (specified by XENMEM_set_memory_map). | 211 | * was started (specified by XENMEM_set_memory_map). |
@@ -217,4 +241,20 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_memory_map); | |||
217 | * during a driver critical region. | 241 | * during a driver critical region. |
218 | */ | 242 | */ |
219 | extern spinlock_t xen_reservation_lock; | 243 | extern spinlock_t xen_reservation_lock; |
244 | |||
245 | /* | ||
246 | * Unmaps the page appearing at a particular GPFN from the specified guest's | ||
247 | * pseudophysical address space. | ||
248 | * arg == addr of xen_remove_from_physmap_t. | ||
249 | */ | ||
250 | #define XENMEM_remove_from_physmap 15 | ||
251 | struct xen_remove_from_physmap { | ||
252 | /* Which domain to change the mapping for. */ | ||
253 | domid_t domid; | ||
254 | |||
255 | /* GPFN of the current mapping of the page. */ | ||
256 | xen_pfn_t gpfn; | ||
257 | }; | ||
258 | DEFINE_GUEST_HANDLE_STRUCT(xen_remove_from_physmap); | ||
259 | |||
220 | #endif /* __XEN_PUBLIC_MEMORY_H__ */ | 260 | #endif /* __XEN_PUBLIC_MEMORY_H__ */ |
diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h index 4755b5fac9c7..5e36932ab407 100644 --- a/include/xen/interface/platform.h +++ b/include/xen/interface/platform.h | |||
@@ -324,6 +324,22 @@ struct xenpf_cpu_ol { | |||
324 | }; | 324 | }; |
325 | DEFINE_GUEST_HANDLE_STRUCT(xenpf_cpu_ol); | 325 | DEFINE_GUEST_HANDLE_STRUCT(xenpf_cpu_ol); |
326 | 326 | ||
327 | /* | ||
328 | * CMD 58 and 59 are reserved for cpu hotadd and memory hotadd, | ||
329 | * which are already occupied at Xen hypervisor side. | ||
330 | */ | ||
331 | #define XENPF_core_parking 60 | ||
332 | struct xenpf_core_parking { | ||
333 | /* IN variables */ | ||
334 | #define XEN_CORE_PARKING_SET 1 | ||
335 | #define XEN_CORE_PARKING_GET 2 | ||
336 | uint32_t type; | ||
337 | /* IN variables: set cpu nums expected to be idled */ | ||
338 | /* OUT variables: get cpu nums actually be idled */ | ||
339 | uint32_t idle_nums; | ||
340 | }; | ||
341 | DEFINE_GUEST_HANDLE_STRUCT(xenpf_core_parking); | ||
342 | |||
327 | struct xen_platform_op { | 343 | struct xen_platform_op { |
328 | uint32_t cmd; | 344 | uint32_t cmd; |
329 | uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ | 345 | uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ |
@@ -341,6 +357,7 @@ struct xen_platform_op { | |||
341 | struct xenpf_set_processor_pminfo set_pminfo; | 357 | struct xenpf_set_processor_pminfo set_pminfo; |
342 | struct xenpf_pcpuinfo pcpu_info; | 358 | struct xenpf_pcpuinfo pcpu_info; |
343 | struct xenpf_cpu_ol cpu_ol; | 359 | struct xenpf_cpu_ol cpu_ol; |
360 | struct xenpf_core_parking core_parking; | ||
344 | uint8_t pad[128]; | 361 | uint8_t pad[128]; |
345 | } u; | 362 | } u; |
346 | }; | 363 | }; |
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index 6a198e46ab6e..d6fe062cad6b 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define INCLUDE_XEN_OPS_H | 2 | #define INCLUDE_XEN_OPS_H |
3 | 3 | ||
4 | #include <linux/percpu.h> | 4 | #include <linux/percpu.h> |
5 | #include <asm/xen/interface.h> | ||
5 | 6 | ||
6 | DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu); | 7 | DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu); |
7 | 8 | ||
@@ -26,7 +27,11 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order); | |||
26 | struct vm_area_struct; | 27 | struct vm_area_struct; |
27 | int xen_remap_domain_mfn_range(struct vm_area_struct *vma, | 28 | int xen_remap_domain_mfn_range(struct vm_area_struct *vma, |
28 | unsigned long addr, | 29 | unsigned long addr, |
29 | unsigned long mfn, int nr, | 30 | xen_pfn_t mfn, int nr, |
30 | pgprot_t prot, unsigned domid); | 31 | pgprot_t prot, unsigned domid, |
32 | struct page **pages); | ||
33 | int xen_unmap_domain_mfn_range(struct vm_area_struct *vma, | ||
34 | int numpgs, struct page **pages); | ||
31 | 35 | ||
36 | bool xen_running_on_version_or_later(unsigned int major, unsigned int minor); | ||
32 | #endif /* INCLUDE_XEN_OPS_H */ | 37 | #endif /* INCLUDE_XEN_OPS_H */ |