aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-07 14:33:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-07 14:33:15 -0400
commite306e3be1cbe5b11d0f8a53a557c205cf27e4979 (patch)
tree0c872d9513794f48b80bab8d32e6dd7e6d5fbb26
parent7f0d32e0c1a7a23216a0f2694ec841f60e9dddfd (diff)
parent8b63c998b31c69fff2c8c8c7e543e3142d9eea71 (diff)
Merge tag 'stable/for-linus-3.17-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull Xen updates from David Vrabel: - remove unused V2 grant table support - note that Konrad is xen-blkkback/front maintainer - add 'xen_nopv' option to disable PV extentions for x86 HVM guests - misc minor cleanups * tag 'stable/for-linus-3.17-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen-pciback: Document the 'quirks' sysfs file xen/pciback: Fix error return code in xen_pcibk_attach() xen/events: drop negativity check of unsigned parameter xen/setup: Remove Identity Map Debug Message xen/events/fifo: remove a unecessary use of BM() xen/events/fifo: ensure all bitops are properly aligned even on x86 xen/events/fifo: reset control block and local HEADs on resume xen/arm: use BUG_ON xen/grant-table: remove support for V2 tables x86/xen: safely map and unmap grant frames when in atomic context MAINTAINERS: Make me the Xen block subsystem (front and back) maintainer xen: Introduce 'xen_nopv' to disable PV extensions for HVM guests.
-rw-r--r--Documentation/ABI/testing/sysfs-driver-pciback13
-rw-r--r--Documentation/kernel-parameters.txt4
-rw-r--r--MAINTAINERS7
-rw-r--r--arch/arm/xen/enlighten.c6
-rw-r--r--arch/arm/xen/grant-table.c6
-rw-r--r--arch/x86/xen/enlighten.c13
-rw-r--r--arch/x86/xen/grant-table.c60
-rw-r--r--arch/x86/xen/p2m.c5
-rw-r--r--drivers/xen/events/events_base.c2
-rw-r--r--drivers/xen/events/events_fifo.c55
-rw-r--r--drivers/xen/grant-table.c309
-rw-r--r--drivers/xen/xen-pciback/xenbus.c1
-rw-r--r--include/xen/grant_table.h30
13 files changed, 88 insertions, 423 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-pciback b/Documentation/ABI/testing/sysfs-driver-pciback
new file mode 100644
index 000000000000..6a733bfa37e6
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-pciback
@@ -0,0 +1,13 @@
1What: /sys/bus/pci/drivers/pciback/quirks
2Date: Oct 2011
3KernelVersion: 3.1
4Contact: xen-devel@lists.xenproject.org
5Description:
6 If the permissive attribute is set, then writing a string in
7 the format of DDDD:BB:DD.F-REG:SIZE:MASK will allow the guest
8 to write and read from the PCI device. That is Domain:Bus:
9 Device.Function-Register:Size:Mask (Domain is optional).
10 For example:
11 #echo 00:19.0-E0:2:FF > /sys/bus/pci/drivers/pciback/quirks
12 will allow the guest to read and write to the configuration
13 register 0x0E.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 664fd887cc37..a8eb6afce6a4 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3745,6 +3745,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
3745 Disables the ticketlock slowpath using Xen PV 3745 Disables the ticketlock slowpath using Xen PV
3746 optimizations. 3746 optimizations.
3747 3747
3748 xen_nopv [X86]
3749 Disables the PV optimizations forcing the HVM guest to
3750 run as generic HVM guest with no PV drivers.
3751
3748 xirc2ps_cs= [NET,PCMCIA] 3752 xirc2ps_cs= [NET,PCMCIA]
3749 Format: 3753 Format:
3750 <irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]] 3754 <irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
diff --git a/MAINTAINERS b/MAINTAINERS
index 946a67e6c4ea..b0981c2f4218 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10066,6 +10066,13 @@ S: Supported
10066F: arch/x86/pci/*xen* 10066F: arch/x86/pci/*xen*
10067F: drivers/pci/*xen* 10067F: drivers/pci/*xen*
10068 10068
10069XEN BLOCK SUBSYSTEM
10070M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
10071L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
10072S: Supported
10073F: drivers/block/xen-blkback/*
10074F: drivers/block/xen*
10075
10069XEN SWIOTLB SUBSYSTEM 10076XEN SWIOTLB SUBSYSTEM
10070M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> 10077M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
10071L: xen-devel@lists.xenproject.org (moderated for non-subscribers) 10078L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index 1e632430570b..98544c5f86e9 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -181,8 +181,7 @@ static void xen_restart(enum reboot_mode reboot_mode, const char *cmd)
181 struct sched_shutdown r = { .reason = SHUTDOWN_reboot }; 181 struct sched_shutdown r = { .reason = SHUTDOWN_reboot };
182 int rc; 182 int rc;
183 rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r); 183 rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
184 if (rc) 184 BUG_ON(rc);
185 BUG();
186} 185}
187 186
188static void xen_power_off(void) 187static void xen_power_off(void)
@@ -190,8 +189,7 @@ static void xen_power_off(void)
190 struct sched_shutdown r = { .reason = SHUTDOWN_poweroff }; 189 struct sched_shutdown r = { .reason = SHUTDOWN_poweroff };
191 int rc; 190 int rc;
192 rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r); 191 rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
193 if (rc) 192 BUG_ON(rc);
194 BUG();
195} 193}
196 194
197static int xen_cpu_notification(struct notifier_block *self, 195static int xen_cpu_notification(struct notifier_block *self,
diff --git a/arch/arm/xen/grant-table.c b/arch/arm/xen/grant-table.c
index 91cf08ba1e95..2c4041c9bac5 100644
--- a/arch/arm/xen/grant-table.c
+++ b/arch/arm/xen/grant-table.c
@@ -45,11 +45,9 @@ void arch_gnttab_unmap(void *shared, unsigned long nr_gframes)
45 return; 45 return;
46} 46}
47 47
48int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes, 48int arch_gnttab_init(unsigned long nr_shared)
49 unsigned long max_nr_gframes,
50 grant_status_t **__shared)
51{ 49{
52 return -ENOSYS; 50 return 0;
53} 51}
54 52
55int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status) 53int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status)
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 94813515fdd6..c0cb11fb5008 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1828,8 +1828,19 @@ static void __init xen_hvm_guest_init(void)
1828 xen_hvm_init_mmu_ops(); 1828 xen_hvm_init_mmu_ops();
1829} 1829}
1830 1830
1831static bool xen_nopv = false;
1832static __init int xen_parse_nopv(char *arg)
1833{
1834 xen_nopv = true;
1835 return 0;
1836}
1837early_param("xen_nopv", xen_parse_nopv);
1838
1831static uint32_t __init xen_hvm_platform(void) 1839static uint32_t __init xen_hvm_platform(void)
1832{ 1840{
1841 if (xen_nopv)
1842 return 0;
1843
1833 if (xen_pv_domain()) 1844 if (xen_pv_domain())
1834 return 0; 1845 return 0;
1835 1846
@@ -1838,6 +1849,8 @@ static uint32_t __init xen_hvm_platform(void)
1838 1849
1839bool xen_hvm_need_lapic(void) 1850bool xen_hvm_need_lapic(void)
1840{ 1851{
1852 if (xen_nopv)
1853 return false;
1841 if (xen_pv_domain()) 1854 if (xen_pv_domain())
1842 return false; 1855 return false;
1843 if (!xen_hvm_domain()) 1856 if (!xen_hvm_domain())
diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c
index ebfa9b2c871d..c0413046483a 100644
--- a/arch/x86/xen/grant-table.c
+++ b/arch/x86/xen/grant-table.c
@@ -49,7 +49,7 @@
49static struct gnttab_vm_area { 49static struct gnttab_vm_area {
50 struct vm_struct *area; 50 struct vm_struct *area;
51 pte_t **ptes; 51 pte_t **ptes;
52} gnttab_shared_vm_area, gnttab_status_vm_area; 52} gnttab_shared_vm_area;
53 53
54int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, 54int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
55 unsigned long max_nr_gframes, 55 unsigned long max_nr_gframes,
@@ -73,43 +73,16 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
73 return 0; 73 return 0;
74} 74}
75 75
76int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
77 unsigned long max_nr_gframes,
78 grant_status_t **__shared)
79{
80 grant_status_t *shared = *__shared;
81 unsigned long addr;
82 unsigned long i;
83
84 if (shared == NULL)
85 *__shared = shared = gnttab_status_vm_area.area->addr;
86
87 addr = (unsigned long)shared;
88
89 for (i = 0; i < nr_gframes; i++) {
90 set_pte_at(&init_mm, addr, gnttab_status_vm_area.ptes[i],
91 mfn_pte(frames[i], PAGE_KERNEL));
92 addr += PAGE_SIZE;
93 }
94
95 return 0;
96}
97
98void arch_gnttab_unmap(void *shared, unsigned long nr_gframes) 76void arch_gnttab_unmap(void *shared, unsigned long nr_gframes)
99{ 77{
100 pte_t **ptes;
101 unsigned long addr; 78 unsigned long addr;
102 unsigned long i; 79 unsigned long i;
103 80
104 if (shared == gnttab_status_vm_area.area->addr)
105 ptes = gnttab_status_vm_area.ptes;
106 else
107 ptes = gnttab_shared_vm_area.ptes;
108
109 addr = (unsigned long)shared; 81 addr = (unsigned long)shared;
110 82
111 for (i = 0; i < nr_gframes; i++) { 83 for (i = 0; i < nr_gframes; i++) {
112 set_pte_at(&init_mm, addr, ptes[i], __pte(0)); 84 set_pte_at(&init_mm, addr, gnttab_shared_vm_area.ptes[i],
85 __pte(0));
113 addr += PAGE_SIZE; 86 addr += PAGE_SIZE;
114 } 87 }
115} 88}
@@ -129,35 +102,12 @@ static int arch_gnttab_valloc(struct gnttab_vm_area *area, unsigned nr_frames)
129 return 0; 102 return 0;
130} 103}
131 104
132static void arch_gnttab_vfree(struct gnttab_vm_area *area) 105int arch_gnttab_init(unsigned long nr_shared)
133{ 106{
134 free_vm_area(area->area);
135 kfree(area->ptes);
136}
137
138int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status)
139{
140 int ret;
141
142 if (!xen_pv_domain()) 107 if (!xen_pv_domain())
143 return 0; 108 return 0;
144 109
145 ret = arch_gnttab_valloc(&gnttab_shared_vm_area, nr_shared); 110 return arch_gnttab_valloc(&gnttab_shared_vm_area, nr_shared);
146 if (ret < 0)
147 return ret;
148
149 /*
150 * Always allocate the space for the status frames in case
151 * we're migrated to a host with V2 support.
152 */
153 ret = arch_gnttab_valloc(&gnttab_status_vm_area, nr_status);
154 if (ret < 0)
155 goto err;
156
157 return 0;
158 err:
159 arch_gnttab_vfree(&gnttab_shared_vm_area);
160 return -ENOMEM;
161} 111}
162 112
163#ifdef CONFIG_XEN_PVH 113#ifdef CONFIG_XEN_PVH
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 9bb3d82ffec8..3172692381ae 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -841,10 +841,9 @@ unsigned long __init set_phys_range_identity(unsigned long pfn_s,
841 pfn = ALIGN(pfn, P2M_PER_PAGE); 841 pfn = ALIGN(pfn, P2M_PER_PAGE);
842 } 842 }
843 843
844 if (!WARN((pfn - pfn_s) != (pfn_e - pfn_s), 844 WARN((pfn - pfn_s) != (pfn_e - pfn_s),
845 "Identity mapping failed. We are %ld short of 1-1 mappings!\n", 845 "Identity mapping failed. We are %ld short of 1-1 mappings!\n",
846 (pfn_e - pfn_s) - (pfn - pfn_s))) 846 (pfn_e - pfn_s) - (pfn - pfn_s));
847 printk(KERN_DEBUG "1-1 mapping on %lx->%lx\n", pfn_s, pfn);
848 847
849 return pfn - pfn_s; 848 return pfn - pfn_s;
850} 849}
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index c919d3d5c845..5b5c5ff273fd 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -246,7 +246,7 @@ static void xen_irq_info_cleanup(struct irq_info *info)
246 */ 246 */
247unsigned int evtchn_from_irq(unsigned irq) 247unsigned int evtchn_from_irq(unsigned irq)
248{ 248{
249 if (unlikely(WARN(irq < 0 || irq >= nr_irqs, "Invalid irq %d!\n", irq))) 249 if (unlikely(WARN(irq >= nr_irqs, "Invalid irq %d!\n", irq)))
250 return 0; 250 return 0;
251 251
252 return info_for_irq(irq)->evtchn; 252 return info_for_irq(irq)->evtchn;
diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c
index 84b4bfb84344..417415d738d0 100644
--- a/drivers/xen/events/events_fifo.c
+++ b/drivers/xen/events/events_fifo.c
@@ -67,10 +67,9 @@ static event_word_t *event_array[MAX_EVENT_ARRAY_PAGES] __read_mostly;
67static unsigned event_array_pages __read_mostly; 67static unsigned event_array_pages __read_mostly;
68 68
69/* 69/*
70 * sync_set_bit() and friends must be unsigned long aligned on non-x86 70 * sync_set_bit() and friends must be unsigned long aligned.
71 * platforms.
72 */ 71 */
73#if !defined(CONFIG_X86) && BITS_PER_LONG > 32 72#if BITS_PER_LONG > 32
74 73
75#define BM(w) (unsigned long *)((unsigned long)w & ~0x7UL) 74#define BM(w) (unsigned long *)((unsigned long)w & ~0x7UL)
76#define EVTCHN_FIFO_BIT(b, w) \ 75#define EVTCHN_FIFO_BIT(b, w) \
@@ -100,6 +99,25 @@ static unsigned evtchn_fifo_nr_channels(void)
100 return event_array_pages * EVENT_WORDS_PER_PAGE; 99 return event_array_pages * EVENT_WORDS_PER_PAGE;
101} 100}
102 101
102static int init_control_block(int cpu,
103 struct evtchn_fifo_control_block *control_block)
104{
105 struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu);
106 struct evtchn_init_control init_control;
107 unsigned int i;
108
109 /* Reset the control block and the local HEADs. */
110 clear_page(control_block);
111 for (i = 0; i < EVTCHN_FIFO_MAX_QUEUES; i++)
112 q->head[i] = 0;
113
114 init_control.control_gfn = virt_to_mfn(control_block);
115 init_control.offset = 0;
116 init_control.vcpu = cpu;
117
118 return HYPERVISOR_event_channel_op(EVTCHNOP_init_control, &init_control);
119}
120
103static void free_unused_array_pages(void) 121static void free_unused_array_pages(void)
104{ 122{
105 unsigned i; 123 unsigned i;
@@ -312,7 +330,7 @@ static void evtchn_fifo_handle_events(unsigned cpu)
312 ready = xchg(&control_block->ready, 0); 330 ready = xchg(&control_block->ready, 0);
313 331
314 while (ready) { 332 while (ready) {
315 q = find_first_bit(BM(&ready), EVTCHN_FIFO_MAX_QUEUES); 333 q = find_first_bit(&ready, EVTCHN_FIFO_MAX_QUEUES);
316 consume_one_event(cpu, control_block, q, &ready); 334 consume_one_event(cpu, control_block, q, &ready);
317 ready |= xchg(&control_block->ready, 0); 335 ready |= xchg(&control_block->ready, 0);
318 } 336 }
@@ -324,7 +342,6 @@ static void evtchn_fifo_resume(void)
324 342
325 for_each_possible_cpu(cpu) { 343 for_each_possible_cpu(cpu) {
326 void *control_block = per_cpu(cpu_control_block, cpu); 344 void *control_block = per_cpu(cpu_control_block, cpu);
327 struct evtchn_init_control init_control;
328 int ret; 345 int ret;
329 346
330 if (!control_block) 347 if (!control_block)
@@ -341,12 +358,7 @@ static void evtchn_fifo_resume(void)
341 continue; 358 continue;
342 } 359 }
343 360
344 init_control.control_gfn = virt_to_mfn(control_block); 361 ret = init_control_block(cpu, control_block);
345 init_control.offset = 0;
346 init_control.vcpu = cpu;
347
348 ret = HYPERVISOR_event_channel_op(EVTCHNOP_init_control,
349 &init_control);
350 if (ret < 0) 362 if (ret < 0)
351 BUG(); 363 BUG();
352 } 364 }
@@ -374,30 +386,25 @@ static const struct evtchn_ops evtchn_ops_fifo = {
374 .resume = evtchn_fifo_resume, 386 .resume = evtchn_fifo_resume,
375}; 387};
376 388
377static int evtchn_fifo_init_control_block(unsigned cpu) 389static int evtchn_fifo_alloc_control_block(unsigned cpu)
378{ 390{
379 struct page *control_block = NULL; 391 void *control_block = NULL;
380 struct evtchn_init_control init_control;
381 int ret = -ENOMEM; 392 int ret = -ENOMEM;
382 393
383 control_block = alloc_page(GFP_KERNEL|__GFP_ZERO); 394 control_block = (void *)__get_free_page(GFP_KERNEL);
384 if (control_block == NULL) 395 if (control_block == NULL)
385 goto error; 396 goto error;
386 397
387 init_control.control_gfn = virt_to_mfn(page_address(control_block)); 398 ret = init_control_block(cpu, control_block);
388 init_control.offset = 0;
389 init_control.vcpu = cpu;
390
391 ret = HYPERVISOR_event_channel_op(EVTCHNOP_init_control, &init_control);
392 if (ret < 0) 399 if (ret < 0)
393 goto error; 400 goto error;
394 401
395 per_cpu(cpu_control_block, cpu) = page_address(control_block); 402 per_cpu(cpu_control_block, cpu) = control_block;
396 403
397 return 0; 404 return 0;
398 405
399 error: 406 error:
400 __free_page(control_block); 407 free_page((unsigned long)control_block);
401 return ret; 408 return ret;
402} 409}
403 410
@@ -411,7 +418,7 @@ static int evtchn_fifo_cpu_notification(struct notifier_block *self,
411 switch (action) { 418 switch (action) {
412 case CPU_UP_PREPARE: 419 case CPU_UP_PREPARE:
413 if (!per_cpu(cpu_control_block, cpu)) 420 if (!per_cpu(cpu_control_block, cpu))
414 ret = evtchn_fifo_init_control_block(cpu); 421 ret = evtchn_fifo_alloc_control_block(cpu);
415 break; 422 break;
416 default: 423 default:
417 break; 424 break;
@@ -428,7 +435,7 @@ int __init xen_evtchn_fifo_init(void)
428 int cpu = get_cpu(); 435 int cpu = get_cpu();
429 int ret; 436 int ret;
430 437
431 ret = evtchn_fifo_init_control_block(cpu); 438 ret = evtchn_fifo_alloc_control_block(cpu);
432 if (ret < 0) 439 if (ret < 0)
433 goto out; 440 goto out;
434 441
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index eeba7544f0cd..c254ae036f18 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -69,7 +69,6 @@ struct grant_frames xen_auto_xlat_grant_frames;
69 69
70static union { 70static union {
71 struct grant_entry_v1 *v1; 71 struct grant_entry_v1 *v1;
72 union grant_entry_v2 *v2;
73 void *addr; 72 void *addr;
74} gnttab_shared; 73} gnttab_shared;
75 74
@@ -120,36 +119,10 @@ struct gnttab_ops {
120 * by bit operations. 119 * by bit operations.
121 */ 120 */
122 int (*query_foreign_access)(grant_ref_t ref); 121 int (*query_foreign_access)(grant_ref_t ref);
123 /*
124 * Grant a domain to access a range of bytes within the page referred by
125 * an available grant entry. Ref parameter is reference of a grant entry
126 * which will be sub-page accessed, domid is id of grantee domain, frame
127 * is frame address of subpage grant, flags is grant type and flag
128 * information, page_off is offset of the range of bytes, and length is
129 * length of bytes to be accessed.
130 */
131 void (*update_subpage_entry)(grant_ref_t ref, domid_t domid,
132 unsigned long frame, int flags,
133 unsigned page_off, unsigned length);
134 /*
135 * Redirect an available grant entry on domain A to another grant
136 * reference of domain B, then allow domain C to use grant reference
137 * of domain B transitively. Ref parameter is an available grant entry
138 * reference on domain A, domid is id of domain C which accesses grant
139 * entry transitively, flags is grant type and flag information,
140 * trans_domid is id of domain B whose grant entry is finally accessed
141 * transitively, trans_gref is grant entry transitive reference of
142 * domain B.
143 */
144 void (*update_trans_entry)(grant_ref_t ref, domid_t domid, int flags,
145 domid_t trans_domid, grant_ref_t trans_gref);
146}; 122};
147 123
148static struct gnttab_ops *gnttab_interface; 124static struct gnttab_ops *gnttab_interface;
149 125
150/*This reflects status of grant entries, so act as a global value*/
151static grant_status_t *grstatus;
152
153static int grant_table_version; 126static int grant_table_version;
154static int grefs_per_grant_frame; 127static int grefs_per_grant_frame;
155 128
@@ -231,7 +204,7 @@ static void put_free_entry(grant_ref_t ref)
231} 204}
232 205
233/* 206/*
234 * Following applies to gnttab_update_entry_v1 and gnttab_update_entry_v2. 207 * Following applies to gnttab_update_entry_v1.
235 * Introducing a valid entry into the grant table: 208 * Introducing a valid entry into the grant table:
236 * 1. Write ent->domid. 209 * 1. Write ent->domid.
237 * 2. Write ent->frame: 210 * 2. Write ent->frame:
@@ -250,15 +223,6 @@ static void gnttab_update_entry_v1(grant_ref_t ref, domid_t domid,
250 gnttab_shared.v1[ref].flags = flags; 223 gnttab_shared.v1[ref].flags = flags;
251} 224}
252 225
253static void gnttab_update_entry_v2(grant_ref_t ref, domid_t domid,
254 unsigned long frame, unsigned flags)
255{
256 gnttab_shared.v2[ref].hdr.domid = domid;
257 gnttab_shared.v2[ref].full_page.frame = frame;
258 wmb();
259 gnttab_shared.v2[ref].hdr.flags = GTF_permit_access | flags;
260}
261
262/* 226/*
263 * Public grant-issuing interface functions 227 * Public grant-issuing interface functions
264 */ 228 */
@@ -285,132 +249,11 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
285} 249}
286EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access); 250EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access);
287 251
288static void gnttab_update_subpage_entry_v2(grant_ref_t ref, domid_t domid,
289 unsigned long frame, int flags,
290 unsigned page_off, unsigned length)
291{
292 gnttab_shared.v2[ref].sub_page.frame = frame;
293 gnttab_shared.v2[ref].sub_page.page_off = page_off;
294 gnttab_shared.v2[ref].sub_page.length = length;
295 gnttab_shared.v2[ref].hdr.domid = domid;
296 wmb();
297 gnttab_shared.v2[ref].hdr.flags =
298 GTF_permit_access | GTF_sub_page | flags;
299}
300
301int gnttab_grant_foreign_access_subpage_ref(grant_ref_t ref, domid_t domid,
302 unsigned long frame, int flags,
303 unsigned page_off,
304 unsigned length)
305{
306 if (flags & (GTF_accept_transfer | GTF_reading |
307 GTF_writing | GTF_transitive))
308 return -EPERM;
309
310 if (gnttab_interface->update_subpage_entry == NULL)
311 return -ENOSYS;
312
313 gnttab_interface->update_subpage_entry(ref, domid, frame, flags,
314 page_off, length);
315
316 return 0;
317}
318EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_subpage_ref);
319
320int gnttab_grant_foreign_access_subpage(domid_t domid, unsigned long frame,
321 int flags, unsigned page_off,
322 unsigned length)
323{
324 int ref, rc;
325
326 ref = get_free_entries(1);
327 if (unlikely(ref < 0))
328 return -ENOSPC;
329
330 rc = gnttab_grant_foreign_access_subpage_ref(ref, domid, frame, flags,
331 page_off, length);
332 if (rc < 0) {
333 put_free_entry(ref);
334 return rc;
335 }
336
337 return ref;
338}
339EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_subpage);
340
341bool gnttab_subpage_grants_available(void)
342{
343 return gnttab_interface->update_subpage_entry != NULL;
344}
345EXPORT_SYMBOL_GPL(gnttab_subpage_grants_available);
346
347static void gnttab_update_trans_entry_v2(grant_ref_t ref, domid_t domid,
348 int flags, domid_t trans_domid,
349 grant_ref_t trans_gref)
350{
351 gnttab_shared.v2[ref].transitive.trans_domid = trans_domid;
352 gnttab_shared.v2[ref].transitive.gref = trans_gref;
353 gnttab_shared.v2[ref].hdr.domid = domid;
354 wmb();
355 gnttab_shared.v2[ref].hdr.flags =
356 GTF_permit_access | GTF_transitive | flags;
357}
358
359int gnttab_grant_foreign_access_trans_ref(grant_ref_t ref, domid_t domid,
360 int flags, domid_t trans_domid,
361 grant_ref_t trans_gref)
362{
363 if (flags & (GTF_accept_transfer | GTF_reading |
364 GTF_writing | GTF_sub_page))
365 return -EPERM;
366
367 if (gnttab_interface->update_trans_entry == NULL)
368 return -ENOSYS;
369
370 gnttab_interface->update_trans_entry(ref, domid, flags, trans_domid,
371 trans_gref);
372
373 return 0;
374}
375EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_trans_ref);
376
377int gnttab_grant_foreign_access_trans(domid_t domid, int flags,
378 domid_t trans_domid,
379 grant_ref_t trans_gref)
380{
381 int ref, rc;
382
383 ref = get_free_entries(1);
384 if (unlikely(ref < 0))
385 return -ENOSPC;
386
387 rc = gnttab_grant_foreign_access_trans_ref(ref, domid, flags,
388 trans_domid, trans_gref);
389 if (rc < 0) {
390 put_free_entry(ref);
391 return rc;
392 }
393
394 return ref;
395}
396EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_trans);
397
398bool gnttab_trans_grants_available(void)
399{
400 return gnttab_interface->update_trans_entry != NULL;
401}
402EXPORT_SYMBOL_GPL(gnttab_trans_grants_available);
403
404static int gnttab_query_foreign_access_v1(grant_ref_t ref) 252static int gnttab_query_foreign_access_v1(grant_ref_t ref)
405{ 253{
406 return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing); 254 return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing);
407} 255}
408 256
409static int gnttab_query_foreign_access_v2(grant_ref_t ref)
410{
411 return grstatus[ref] & (GTF_reading|GTF_writing);
412}
413
414int gnttab_query_foreign_access(grant_ref_t ref) 257int gnttab_query_foreign_access(grant_ref_t ref)
415{ 258{
416 return gnttab_interface->query_foreign_access(ref); 259 return gnttab_interface->query_foreign_access(ref);
@@ -433,29 +276,6 @@ static int gnttab_end_foreign_access_ref_v1(grant_ref_t ref, int readonly)
433 return 1; 276 return 1;
434} 277}
435 278
436static int gnttab_end_foreign_access_ref_v2(grant_ref_t ref, int readonly)
437{
438 gnttab_shared.v2[ref].hdr.flags = 0;
439 mb();
440 if (grstatus[ref] & (GTF_reading|GTF_writing)) {
441 return 0;
442 } else {
443 /* The read of grstatus needs to have acquire
444 semantics. On x86, reads already have
445 that, and we just need to protect against
446 compiler reorderings. On other
447 architectures we may need a full
448 barrier. */
449#ifdef CONFIG_X86
450 barrier();
451#else
452 mb();
453#endif
454 }
455
456 return 1;
457}
458
459static inline int _gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly) 279static inline int _gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
460{ 280{
461 return gnttab_interface->end_foreign_access_ref(ref, readonly); 281 return gnttab_interface->end_foreign_access_ref(ref, readonly);
@@ -616,37 +436,6 @@ static unsigned long gnttab_end_foreign_transfer_ref_v1(grant_ref_t ref)
616 return frame; 436 return frame;
617} 437}
618 438
619static unsigned long gnttab_end_foreign_transfer_ref_v2(grant_ref_t ref)
620{
621 unsigned long frame;
622 u16 flags;
623 u16 *pflags;
624
625 pflags = &gnttab_shared.v2[ref].hdr.flags;
626
627 /*
628 * If a transfer is not even yet started, try to reclaim the grant
629 * reference and return failure (== 0).
630 */
631 while (!((flags = *pflags) & GTF_transfer_committed)) {
632 if (sync_cmpxchg(pflags, flags, 0) == flags)
633 return 0;
634 cpu_relax();
635 }
636
637 /* If a transfer is in progress then wait until it is completed. */
638 while (!(flags & GTF_transfer_completed)) {
639 flags = *pflags;
640 cpu_relax();
641 }
642
643 rmb(); /* Read the frame number /after/ reading completion status. */
644 frame = gnttab_shared.v2[ref].full_page.frame;
645 BUG_ON(frame == 0);
646
647 return frame;
648}
649
650unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref) 439unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref)
651{ 440{
652 return gnttab_interface->end_foreign_transfer_ref(ref); 441 return gnttab_interface->end_foreign_transfer_ref(ref);
@@ -962,12 +751,6 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
962} 751}
963EXPORT_SYMBOL_GPL(gnttab_unmap_refs); 752EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
964 753
965static unsigned nr_status_frames(unsigned nr_grant_frames)
966{
967 BUG_ON(grefs_per_grant_frame == 0);
968 return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP;
969}
970
971static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) 754static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes)
972{ 755{
973 int rc; 756 int rc;
@@ -985,55 +768,6 @@ static void gnttab_unmap_frames_v1(void)
985 arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames); 768 arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
986} 769}
987 770
988static int gnttab_map_frames_v2(xen_pfn_t *frames, unsigned int nr_gframes)
989{
990 uint64_t *sframes;
991 unsigned int nr_sframes;
992 struct gnttab_get_status_frames getframes;
993 int rc;
994
995 nr_sframes = nr_status_frames(nr_gframes);
996
997 /* No need for kzalloc as it is initialized in following hypercall
998 * GNTTABOP_get_status_frames.
999 */
1000 sframes = kmalloc(nr_sframes * sizeof(uint64_t), GFP_ATOMIC);
1001 if (!sframes)
1002 return -ENOMEM;
1003
1004 getframes.dom = DOMID_SELF;
1005 getframes.nr_frames = nr_sframes;
1006 set_xen_guest_handle(getframes.frame_list, sframes);
1007
1008 rc = HYPERVISOR_grant_table_op(GNTTABOP_get_status_frames,
1009 &getframes, 1);
1010 if (rc == -ENOSYS) {
1011 kfree(sframes);
1012 return -ENOSYS;
1013 }
1014
1015 BUG_ON(rc || getframes.status);
1016
1017 rc = arch_gnttab_map_status(sframes, nr_sframes,
1018 nr_status_frames(gnttab_max_grant_frames()),
1019 &grstatus);
1020 BUG_ON(rc);
1021 kfree(sframes);
1022
1023 rc = arch_gnttab_map_shared(frames, nr_gframes,
1024 gnttab_max_grant_frames(),
1025 &gnttab_shared.addr);
1026 BUG_ON(rc);
1027
1028 return 0;
1029}
1030
1031static void gnttab_unmap_frames_v2(void)
1032{
1033 arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
1034 arch_gnttab_unmap(grstatus, nr_status_frames(nr_grant_frames));
1035}
1036
1037static int gnttab_map(unsigned int start_idx, unsigned int end_idx) 771static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
1038{ 772{
1039 struct gnttab_setup_table setup; 773 struct gnttab_setup_table setup;
@@ -1101,43 +835,13 @@ static struct gnttab_ops gnttab_v1_ops = {
1101 .query_foreign_access = gnttab_query_foreign_access_v1, 835 .query_foreign_access = gnttab_query_foreign_access_v1,
1102}; 836};
1103 837
1104static struct gnttab_ops gnttab_v2_ops = {
1105 .map_frames = gnttab_map_frames_v2,
1106 .unmap_frames = gnttab_unmap_frames_v2,
1107 .update_entry = gnttab_update_entry_v2,
1108 .end_foreign_access_ref = gnttab_end_foreign_access_ref_v2,
1109 .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v2,
1110 .query_foreign_access = gnttab_query_foreign_access_v2,
1111 .update_subpage_entry = gnttab_update_subpage_entry_v2,
1112 .update_trans_entry = gnttab_update_trans_entry_v2,
1113};
1114
1115static void gnttab_request_version(void) 838static void gnttab_request_version(void)
1116{ 839{
1117 int rc; 840 /* Only version 1 is used, which will always be available. */
1118 struct gnttab_set_version gsv; 841 grant_table_version = 1;
842 grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1);
843 gnttab_interface = &gnttab_v1_ops;
1119 844
1120 gsv.version = 1;
1121
1122 rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
1123 if (rc == 0 && gsv.version == 2) {
1124 grant_table_version = 2;
1125 grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2);
1126 gnttab_interface = &gnttab_v2_ops;
1127 } else if (grant_table_version == 2) {
1128 /*
1129 * If we've already used version 2 features,
1130 * but then suddenly discover that they're not
1131 * available (e.g. migrating to an older
1132 * version of Xen), almost unbounded badness
1133 * can happen.
1134 */
1135 panic("we need grant tables version 2, but only version 1 is available");
1136 } else {
1137 grant_table_version = 1;
1138 grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1);
1139 gnttab_interface = &gnttab_v1_ops;
1140 }
1141 pr_info("Grant tables using version %d layout\n", grant_table_version); 845 pr_info("Grant tables using version %d layout\n", grant_table_version);
1142} 846}
1143 847
@@ -1225,8 +929,7 @@ int gnttab_init(void)
1225 } 929 }
1226 } 930 }
1227 931
1228 ret = arch_gnttab_init(max_nr_grant_frames, 932 ret = arch_gnttab_init(max_nr_grant_frames);
1229 nr_status_frames(max_nr_grant_frames));
1230 if (ret < 0) 933 if (ret < 0)
1231 goto ini_nomem; 934 goto ini_nomem;
1232 935
diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c
index 4a7e6e0a5f4c..c214daab4829 100644
--- a/drivers/xen/xen-pciback/xenbus.c
+++ b/drivers/xen/xen-pciback/xenbus.c
@@ -174,6 +174,7 @@ static int xen_pcibk_attach(struct xen_pcibk_device *pdev)
174 "version mismatch (%s/%s) with pcifront - " 174 "version mismatch (%s/%s) with pcifront - "
175 "halting " DRV_NAME, 175 "halting " DRV_NAME,
176 magic, XEN_PCI_MAGIC); 176 magic, XEN_PCI_MAGIC);
177 err = -EFAULT;
177 goto out; 178 goto out;
178 } 179 }
179 180
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index 5c1aba154b64..3387465b9caa 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -64,24 +64,6 @@ int gnttab_resume(void);
64 64
65int gnttab_grant_foreign_access(domid_t domid, unsigned long frame, 65int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
66 int readonly); 66 int readonly);
67int gnttab_grant_foreign_access_subpage(domid_t domid, unsigned long frame,
68 int flags, unsigned page_off,
69 unsigned length);
70int gnttab_grant_foreign_access_trans(domid_t domid, int flags,
71 domid_t trans_domid,
72 grant_ref_t trans_gref);
73
74/*
75 * Are sub-page grants available on this version of Xen? Returns true if they
76 * are, and false if they're not.
77 */
78bool gnttab_subpage_grants_available(void);
79
80/*
81 * Are transitive grants available on this version of Xen? Returns true if they
82 * are, and false if they're not.
83 */
84bool gnttab_trans_grants_available(void);
85 67
86/* 68/*
87 * End access through the given grant reference, iff the grant entry is no 69 * End access through the given grant reference, iff the grant entry is no
@@ -128,13 +110,6 @@ void gnttab_cancel_free_callback(struct gnttab_free_callback *callback);
128 110
129void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, 111void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
130 unsigned long frame, int readonly); 112 unsigned long frame, int readonly);
131int gnttab_grant_foreign_access_subpage_ref(grant_ref_t ref, domid_t domid,
132 unsigned long frame, int flags,
133 unsigned page_off,
134 unsigned length);
135int gnttab_grant_foreign_access_trans_ref(grant_ref_t ref, domid_t domid,
136 int flags, domid_t trans_domid,
137 grant_ref_t trans_gref);
138 113
139void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid, 114void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
140 unsigned long pfn); 115 unsigned long pfn);
@@ -170,13 +145,10 @@ gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, phys_addr_t addr,
170 unmap->dev_bus_addr = 0; 145 unmap->dev_bus_addr = 0;
171} 146}
172 147
173int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status); 148int arch_gnttab_init(unsigned long nr_shared);
174int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes, 149int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes,
175 unsigned long max_nr_gframes, 150 unsigned long max_nr_gframes,
176 void **__shared); 151 void **__shared);
177int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
178 unsigned long max_nr_gframes,
179 grant_status_t **__shared);
180void arch_gnttab_unmap(void *shared, unsigned long nr_gframes); 152void arch_gnttab_unmap(void *shared, unsigned long nr_gframes);
181 153
182struct grant_frames { 154struct grant_frames {