aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen
diff options
context:
space:
mode:
authorAnnie Li <annie.li@oracle.com>2011-11-21 20:59:21 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-11-22 09:24:51 -0500
commit85ff6acb075a484780b3d763fdf41596d8fc0970 (patch)
tree30c3f1622c525036e1cefc8ade5853c0be700cb4 /drivers/xen
parentb1e495b2fae578b1bd3ab1906cb15aac43f96fee (diff)
xen/granttable: Grant tables V2 implementation
Receiver-side copying of packets is based on this implementation, it gives better performance and better CPU accounting. It totally supports three types: full-page, sub-page and transitive grants. However this patch does not cover sub-page and transitive grants, it mainly focus on Full-page part and implements grant table V2 interfaces corresponding to what already exists in grant table V1, such as: grant table V2 initialization, mapping, releasing and exported interfaces. Each guest can only supports one type of grant table type, every entry in grant table should be the same version. It is necessary to set V1 or V2 version before initializing the grant table. Grant table exported interfaces of V2 are same with those of V1, Xen is responsible to judge what grant table version guests are using in every grant operation. V2 fulfills the same role of V1, and it is totally backwards compitable with V1. If dom0 support grant table V2, the guests runing on it can run with either V1 or V2. Acked-by: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: Annie Li <annie.li@oracle.com> [v1: Modified alloc_vm_area call (new parameters), indentation, and cleanpatch warnings] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen')
-rw-r--r--drivers/xen/grant-table.c171
1 files changed, 167 insertions, 4 deletions
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 0518d0404942..301869f60dc7 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -44,6 +44,7 @@
44#include <xen/page.h> 44#include <xen/page.h>
45#include <xen/grant_table.h> 45#include <xen/grant_table.h>
46#include <xen/interface/memory.h> 46#include <xen/interface/memory.h>
47#include <xen/hvc-console.h>
47#include <asm/xen/hypercall.h> 48#include <asm/xen/hypercall.h>
48 49
49#include <asm/pgtable.h> 50#include <asm/pgtable.h>
@@ -53,7 +54,10 @@
53/* External tools reserve first few grant table entries. */ 54/* External tools reserve first few grant table entries. */
54#define NR_RESERVED_ENTRIES 8 55#define NR_RESERVED_ENTRIES 8
55#define GNTTAB_LIST_END 0xffffffff 56#define GNTTAB_LIST_END 0xffffffff
56#define GREFS_PER_GRANT_FRAME (PAGE_SIZE / sizeof(struct grant_entry_v1)) 57#define GREFS_PER_GRANT_FRAME \
58(grant_table_version == 1 ? \
59(PAGE_SIZE / sizeof(struct grant_entry_v1)) : \
60(PAGE_SIZE / sizeof(union grant_entry_v2)))
57 61
58static grant_ref_t **gnttab_list; 62static grant_ref_t **gnttab_list;
59static unsigned int nr_grant_frames; 63static unsigned int nr_grant_frames;
@@ -66,6 +70,7 @@ EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
66 70
67static union { 71static union {
68 struct grant_entry_v1 *v1; 72 struct grant_entry_v1 *v1;
73 union grant_entry_v2 *v2;
69 void *addr; 74 void *addr;
70} gnttab_shared; 75} gnttab_shared;
71 76
@@ -120,6 +125,9 @@ struct gnttab_ops {
120 125
121static struct gnttab_ops *gnttab_interface; 126static struct gnttab_ops *gnttab_interface;
122 127
128/*This reflects status of grant entries, so act as a global value*/
129static grant_status_t *grstatus;
130
123static int grant_table_version; 131static int grant_table_version;
124 132
125static struct gnttab_free_callback *gnttab_free_callback_list; 133static struct gnttab_free_callback *gnttab_free_callback_list;
@@ -127,6 +135,7 @@ static struct gnttab_free_callback *gnttab_free_callback_list;
127static int gnttab_expand(unsigned int req_entries); 135static int gnttab_expand(unsigned int req_entries);
128 136
129#define RPP (PAGE_SIZE / sizeof(grant_ref_t)) 137#define RPP (PAGE_SIZE / sizeof(grant_ref_t))
138#define SPP (PAGE_SIZE / sizeof(grant_status_t))
130 139
131static inline grant_ref_t *__gnttab_entry(grant_ref_t entry) 140static inline grant_ref_t *__gnttab_entry(grant_ref_t entry)
132{ 141{
@@ -199,6 +208,7 @@ static void put_free_entry(grant_ref_t ref)
199} 208}
200 209
201/* 210/*
211 * Following applies to gnttab_update_entry_v1 and gnttab_update_entry_v2.
202 * Introducing a valid entry into the grant table: 212 * Introducing a valid entry into the grant table:
203 * 1. Write ent->domid. 213 * 1. Write ent->domid.
204 * 2. Write ent->frame: 214 * 2. Write ent->frame:
@@ -217,6 +227,15 @@ static void gnttab_update_entry_v1(grant_ref_t ref, domid_t domid,
217 gnttab_shared.v1[ref].flags = flags; 227 gnttab_shared.v1[ref].flags = flags;
218} 228}
219 229
230static void gnttab_update_entry_v2(grant_ref_t ref, domid_t domid,
231 unsigned long frame, unsigned flags)
232{
233 gnttab_shared.v2[ref].hdr.domid = domid;
234 gnttab_shared.v2[ref].full_page.frame = frame;
235 wmb();
236 gnttab_shared.v2[ref].hdr.flags = GTF_permit_access | flags;
237}
238
220/* 239/*
221 * Public grant-issuing interface functions 240 * Public grant-issuing interface functions
222 */ 241 */
@@ -248,6 +267,11 @@ static int gnttab_query_foreign_access_v1(grant_ref_t ref)
248 return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing); 267 return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing);
249} 268}
250 269
270static int gnttab_query_foreign_access_v2(grant_ref_t ref)
271{
272 return grstatus[ref] & (GTF_reading|GTF_writing);
273}
274
251int gnttab_query_foreign_access(grant_ref_t ref) 275int gnttab_query_foreign_access(grant_ref_t ref)
252{ 276{
253 return gnttab_interface->query_foreign_access(ref); 277 return gnttab_interface->query_foreign_access(ref);
@@ -272,6 +296,29 @@ static int gnttab_end_foreign_access_ref_v1(grant_ref_t ref, int readonly)
272 return 1; 296 return 1;
273} 297}
274 298
299static int gnttab_end_foreign_access_ref_v2(grant_ref_t ref, int readonly)
300{
301 gnttab_shared.v2[ref].hdr.flags = 0;
302 mb();
303 if (grstatus[ref] & (GTF_reading|GTF_writing)) {
304 return 0;
305 } else {
306 /* The read of grstatus needs to have acquire
307 semantics. On x86, reads already have
308 that, and we just need to protect against
309 compiler reorderings. On other
310 architectures we may need a full
311 barrier. */
312#ifdef CONFIG_X86
313 barrier();
314#else
315 mb();
316#endif
317 }
318
319 return 1;
320}
321
275int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly) 322int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
276{ 323{
277 return gnttab_interface->end_foreign_access_ref(ref, readonly); 324 return gnttab_interface->end_foreign_access_ref(ref, readonly);
@@ -345,6 +392,37 @@ static unsigned long gnttab_end_foreign_transfer_ref_v1(grant_ref_t ref)
345 return frame; 392 return frame;
346} 393}
347 394
395static unsigned long gnttab_end_foreign_transfer_ref_v2(grant_ref_t ref)
396{
397 unsigned long frame;
398 u16 flags;
399 u16 *pflags;
400
401 pflags = &gnttab_shared.v2[ref].hdr.flags;
402
403 /*
404 * If a transfer is not even yet started, try to reclaim the grant
405 * reference and return failure (== 0).
406 */
407 while (!((flags = *pflags) & GTF_transfer_committed)) {
408 if (sync_cmpxchg(pflags, flags, 0) == flags)
409 return 0;
410 cpu_relax();
411 }
412
413 /* If a transfer is in progress then wait until it is completed. */
414 while (!(flags & GTF_transfer_completed)) {
415 flags = *pflags;
416 cpu_relax();
417 }
418
419 rmb(); /* Read the frame number /after/ reading completion status. */
420 frame = gnttab_shared.v2[ref].full_page.frame;
421 BUG_ON(frame == 0);
422
423 return frame;
424}
425
348unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref) 426unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref)
349{ 427{
350 return gnttab_interface->end_foreign_transfer_ref(ref); 428 return gnttab_interface->end_foreign_transfer_ref(ref);
@@ -592,6 +670,11 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
592} 670}
593EXPORT_SYMBOL_GPL(gnttab_unmap_refs); 671EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
594 672
673static unsigned nr_status_frames(unsigned nr_grant_frames)
674{
675 return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP;
676}
677
595static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes) 678static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes)
596{ 679{
597 int rc; 680 int rc;
@@ -606,7 +689,56 @@ static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes)
606 689
607static void gnttab_unmap_frames_v1(void) 690static void gnttab_unmap_frames_v1(void)
608{ 691{
609 arch_gnttab_unmap_shared(gnttab_shared.addr, nr_grant_frames); 692 arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
693}
694
695static int gnttab_map_frames_v2(unsigned long *frames, unsigned int nr_gframes)
696{
697 uint64_t *sframes;
698 unsigned int nr_sframes;
699 struct gnttab_get_status_frames getframes;
700 int rc;
701
702 nr_sframes = nr_status_frames(nr_gframes);
703
704 /* No need for kzalloc as it is initialized in following hypercall
705 * GNTTABOP_get_status_frames.
706 */
707 sframes = kmalloc(nr_sframes * sizeof(uint64_t), GFP_ATOMIC);
708 if (!sframes)
709 return -ENOMEM;
710
711 getframes.dom = DOMID_SELF;
712 getframes.nr_frames = nr_sframes;
713 set_xen_guest_handle(getframes.frame_list, sframes);
714
715 rc = HYPERVISOR_grant_table_op(GNTTABOP_get_status_frames,
716 &getframes, 1);
717 if (rc == -ENOSYS) {
718 kfree(sframes);
719 return -ENOSYS;
720 }
721
722 BUG_ON(rc || getframes.status);
723
724 rc = arch_gnttab_map_status(sframes, nr_sframes,
725 nr_status_frames(gnttab_max_grant_frames()),
726 &grstatus);
727 BUG_ON(rc);
728 kfree(sframes);
729
730 rc = arch_gnttab_map_shared(frames, nr_gframes,
731 gnttab_max_grant_frames(),
732 &gnttab_shared.addr);
733 BUG_ON(rc);
734
735 return 0;
736}
737
738static void gnttab_unmap_frames_v2(void)
739{
740 arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
741 arch_gnttab_unmap(grstatus, nr_status_frames(nr_grant_frames));
610} 742}
611 743
612static int gnttab_map(unsigned int start_idx, unsigned int end_idx) 744static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
@@ -640,6 +772,9 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
640 return rc; 772 return rc;
641 } 773 }
642 774
775 /* No need for kzalloc as it is initialized in following hypercall
776 * GNTTABOP_setup_table.
777 */
643 frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC); 778 frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC);
644 if (!frames) 779 if (!frames)
645 return -ENOMEM; 780 return -ENOMEM;
@@ -672,10 +807,38 @@ static struct gnttab_ops gnttab_v1_ops = {
672 .query_foreign_access = gnttab_query_foreign_access_v1, 807 .query_foreign_access = gnttab_query_foreign_access_v1,
673}; 808};
674 809
810static struct gnttab_ops gnttab_v2_ops = {
811 .map_frames = gnttab_map_frames_v2,
812 .unmap_frames = gnttab_unmap_frames_v2,
813 .update_entry = gnttab_update_entry_v2,
814 .end_foreign_access_ref = gnttab_end_foreign_access_ref_v2,
815 .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v2,
816 .query_foreign_access = gnttab_query_foreign_access_v2,
817};
818
675static void gnttab_request_version(void) 819static void gnttab_request_version(void)
676{ 820{
677 grant_table_version = 1; 821 int rc;
678 gnttab_interface = &gnttab_v1_ops; 822 struct gnttab_set_version gsv;
823
824 gsv.version = 2;
825 rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
826 if (rc == 0) {
827 grant_table_version = 2;
828 gnttab_interface = &gnttab_v2_ops;
829 } else if (grant_table_version == 2) {
830 /*
831 * If we've already used version 2 features,
832 * but then suddenly discover that they're not
833 * available (e.g. migrating to an older
834 * version of Xen), almost unbounded badness
835 * can happen.
836 */
837 panic("we need grant tables version 2, but only version 1 is available");
838 } else {
839 grant_table_version = 1;
840 gnttab_interface = &gnttab_v1_ops;
841 }
679 printk(KERN_INFO "Grant tables using version %d layout.\n", 842 printk(KERN_INFO "Grant tables using version %d layout.\n",
680 grant_table_version); 843 grant_table_version);
681} 844}