aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/grant-table.c
diff options
context:
space:
mode:
authorAnnie Li <annie.li@oracle.com>2011-11-21 20:58:06 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-11-22 09:23:44 -0500
commit0f9f5a9588468cddeccc9146b86798492c7cd4f5 (patch)
tree2743d8d40497383c1f4edc92d3ee9ddbf42d28a9 /drivers/xen/grant-table.c
parent3b456ae900705dda029f81a6cceed64d7f1ddfbd (diff)
xen/granttable: Introducing grant table V2 stucture
This patch introduces new structures of grant table V2, grant table V2 is an extension from V1. Grant table is shared between guest and Xen, and Xen is responsible to do corresponding work for grant operations, such as: figure out guest's grant table version, perform different actions based on different grant table version, etc. Although full-page structure of V2 is different from V1, it play the same role as V1. Acked-by: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: Annie Li <annie.li@oracle.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen/grant-table.c')
-rw-r--r--drivers/xen/grant-table.c181
1 files changed, 141 insertions, 40 deletions
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index bf1c094f4ebf..18355a53763f 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -53,7 +53,7 @@
53/* External tools reserve first few grant table entries. */ 53/* External tools reserve first few grant table entries. */
54#define NR_RESERVED_ENTRIES 8 54#define NR_RESERVED_ENTRIES 8
55#define GNTTAB_LIST_END 0xffffffff 55#define GNTTAB_LIST_END 0xffffffff
56#define GREFS_PER_GRANT_FRAME (PAGE_SIZE / sizeof(struct grant_entry)) 56#define GREFS_PER_GRANT_FRAME (PAGE_SIZE / sizeof(struct grant_entry_v1))
57 57
58static grant_ref_t **gnttab_list; 58static grant_ref_t **gnttab_list;
59static unsigned int nr_grant_frames; 59static unsigned int nr_grant_frames;
@@ -64,7 +64,63 @@ static DEFINE_SPINLOCK(gnttab_list_lock);
64unsigned long xen_hvm_resume_frames; 64unsigned long xen_hvm_resume_frames;
65EXPORT_SYMBOL_GPL(xen_hvm_resume_frames); 65EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
66 66
67static struct grant_entry *shared; 67static union {
68 struct grant_entry_v1 *v1;
69 void *addr;
70} gnttab_shared;
71
72/*This is a structure of function pointers for grant table*/
73struct gnttab_ops {
74 /*
75 * Mapping a list of frames for storing grant entries. First input
76 * parameter is used to storing grant table address when grant table
77 * being setup, second parameter is the number of frames to map grant
78 * table. Returning GNTST_okay means success and negative value means
79 * failure.
80 */
81 int (*map_frames)(unsigned long *, unsigned int);
82 /*
83 * Release a list of frames which are mapped in map_frames for grant
84 * entry status.
85 */
86 void (*unmap_frames)(void);
87 /*
88 * Introducing a valid entry into the grant table, granting the frame
89 * of this grant entry to domain for accessing, or transfering, or
90 * transitively accessing. First input parameter is reference of this
91 * introduced grant entry, second one is domid of granted domain, third
92 * one is the frame to be granted, and the last one is status of the
93 * grant entry to be updated.
94 */
95 void (*update_entry)(grant_ref_t, domid_t, unsigned long, unsigned);
96 /*
97 * Stop granting a grant entry to domain for accessing. First input
98 * parameter is reference of a grant entry whose grant access will be
99 * stopped, second one is not in use now. If the grant entry is
100 * currently mapped for reading or writing, just return failure(==0)
101 * directly and don't tear down the grant access. Otherwise, stop grant
102 * access for this entry and return success(==1).
103 */
104 int (*end_foreign_access_ref)(grant_ref_t, int);
105 /*
106 * Stop granting a grant entry to domain for transfer. If tranfer has
107 * not started, just reclaim the grant entry and return failure(==0).
108 * Otherwise, wait for the transfer to complete and then return the
109 * frame.
110 */
111 unsigned long (*end_foreign_transfer_ref)(grant_ref_t);
112 /*
113 * Query the status of a grant entry. Input parameter is reference of
114 * queried grant entry, return value is the status of queried entry.
115 * Detailed status(writing/reading) can be gotten from the return value
116 * by bit operations.
117 */
118 int (*query_foreign_access)(grant_ref_t);
119};
120
121static struct gnttab_ops *gnttab_interface;
122
123static int grant_table_version;
68 124
69static struct gnttab_free_callback *gnttab_free_callback_list; 125static struct gnttab_free_callback *gnttab_free_callback_list;
70 126
@@ -142,23 +198,23 @@ static void put_free_entry(grant_ref_t ref)
142 spin_unlock_irqrestore(&gnttab_list_lock, flags); 198 spin_unlock_irqrestore(&gnttab_list_lock, flags);
143} 199}
144 200
145static void update_grant_entry(grant_ref_t ref, domid_t domid, 201/*
146 unsigned long frame, unsigned flags) 202 * Introducing a valid entry into the grant table:
203 * 1. Write ent->domid.
204 * 2. Write ent->frame:
205 * GTF_permit_access: Frame to which access is permitted.
206 * GTF_accept_transfer: Pseudo-phys frame slot being filled by new
207 * frame, or zero if none.
208 * 3. Write memory barrier (WMB).
209 * 4. Write ent->flags, inc. valid type.
210 */
211static void gnttab_update_entry_v1(grant_ref_t ref, domid_t domid,
212 unsigned long frame, unsigned flags)
147{ 213{
148 /* 214 gnttab_shared.v1[ref].domid = domid;
149 * Introducing a valid entry into the grant table: 215 gnttab_shared.v1[ref].frame = frame;
150 * 1. Write ent->domid.
151 * 2. Write ent->frame:
152 * GTF_permit_access: Frame to which access is permitted.
153 * GTF_accept_transfer: Pseudo-phys frame slot being filled by new
154 * frame, or zero if none.
155 * 3. Write memory barrier (WMB).
156 * 4. Write ent->flags, inc. valid type.
157 */
158 shared[ref].frame = frame;
159 shared[ref].domid = domid;
160 wmb(); 216 wmb();
161 shared[ref].flags = flags; 217 gnttab_shared.v1[ref].flags = flags;
162} 218}
163 219
164/* 220/*
@@ -167,7 +223,7 @@ static void update_grant_entry(grant_ref_t ref, domid_t domid,
167void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, 223void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
168 unsigned long frame, int readonly) 224 unsigned long frame, int readonly)
169{ 225{
170 update_grant_entry(ref, domid, frame, 226 gnttab_interface->update_entry(ref, domid, frame,
171 GTF_permit_access | (readonly ? GTF_readonly : 0)); 227 GTF_permit_access | (readonly ? GTF_readonly : 0));
172} 228}
173EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref); 229EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref);
@@ -187,31 +243,37 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
187} 243}
188EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access); 244EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access);
189 245
190int gnttab_query_foreign_access(grant_ref_t ref) 246static int gnttab_query_foreign_access_v1(grant_ref_t ref)
191{ 247{
192 u16 nflags; 248 return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing);
193 249}
194 nflags = shared[ref].flags;
195 250
196 return nflags & (GTF_reading|GTF_writing); 251int gnttab_query_foreign_access(grant_ref_t ref)
252{
253 return gnttab_interface->query_foreign_access(ref);
197} 254}
198EXPORT_SYMBOL_GPL(gnttab_query_foreign_access); 255EXPORT_SYMBOL_GPL(gnttab_query_foreign_access);
199 256
200int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly) 257static int gnttab_end_foreign_access_ref_v1(grant_ref_t ref, int readonly)
201{ 258{
202 u16 flags, nflags; 259 u16 flags, nflags;
203 260
204 nflags = shared[ref].flags; 261 nflags = gnttab_shared.v1[ref].flags;
205 do { 262 do {
206 flags = nflags; 263 flags = nflags;
207 if (flags & (GTF_reading|GTF_writing)) { 264 if (flags & (GTF_reading|GTF_writing)) {
208 printk(KERN_ALERT "WARNING: g.e. still in use!\n"); 265 printk(KERN_ALERT "WARNING: g.e. still in use!\n");
209 return 0; 266 return 0;
210 } 267 }
211 } while ((nflags = sync_cmpxchg(&shared[ref].flags, flags, 0)) != flags); 268 } while ((nflags = sync_cmpxchg(&gnttab_shared.v1[ref].flags, flags, 0)) != flags);
212 269
213 return 1; 270 return 1;
214} 271}
272
273int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
274{
275 return gnttab_interface->end_foreign_access_ref(ref, readonly);
276}
215EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref); 277EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref);
216 278
217void gnttab_end_foreign_access(grant_ref_t ref, int readonly, 279void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
@@ -246,11 +308,11 @@ EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer);
246void gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid, 308void gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
247 unsigned long pfn) 309 unsigned long pfn)
248{ 310{
249 update_grant_entry(ref, domid, pfn, GTF_accept_transfer); 311 gnttab_interface->update_entry(ref, domid, pfn, GTF_accept_transfer);
250} 312}
251EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref); 313EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref);
252 314
253unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref) 315static unsigned long gnttab_end_foreign_transfer_ref_v1(grant_ref_t ref)
254{ 316{
255 unsigned long frame; 317 unsigned long frame;
256 u16 flags; 318 u16 flags;
@@ -259,24 +321,29 @@ unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref)
259 * If a transfer is not even yet started, try to reclaim the grant 321 * If a transfer is not even yet started, try to reclaim the grant
260 * reference and return failure (== 0). 322 * reference and return failure (== 0).
261 */ 323 */
262 while (!((flags = shared[ref].flags) & GTF_transfer_committed)) { 324 while (!((flags = gnttab_shared.v1[ref].flags) & GTF_transfer_committed)) {
263 if (sync_cmpxchg(&shared[ref].flags, flags, 0) == flags) 325 if (sync_cmpxchg(&gnttab_shared.v1[ref].flags, flags, 0) == flags)
264 return 0; 326 return 0;
265 cpu_relax(); 327 cpu_relax();
266 } 328 }
267 329
268 /* If a transfer is in progress then wait until it is completed. */ 330 /* If a transfer is in progress then wait until it is completed. */
269 while (!(flags & GTF_transfer_completed)) { 331 while (!(flags & GTF_transfer_completed)) {
270 flags = shared[ref].flags; 332 flags = gnttab_shared.v1[ref].flags;
271 cpu_relax(); 333 cpu_relax();
272 } 334 }
273 335
274 rmb(); /* Read the frame number /after/ reading completion status. */ 336 rmb(); /* Read the frame number /after/ reading completion status. */
275 frame = shared[ref].frame; 337 frame = gnttab_shared.v1[ref].frame;
276 BUG_ON(frame == 0); 338 BUG_ON(frame == 0);
277 339
278 return frame; 340 return frame;
279} 341}
342
343unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref)
344{
345 return gnttab_interface->end_foreign_transfer_ref(ref);
346}
280EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref); 347EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref);
281 348
282unsigned long gnttab_end_foreign_transfer(grant_ref_t ref) 349unsigned long gnttab_end_foreign_transfer(grant_ref_t ref)
@@ -520,6 +587,23 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
520} 587}
521EXPORT_SYMBOL_GPL(gnttab_unmap_refs); 588EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
522 589
590static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes)
591{
592 int rc;
593
594 rc = arch_gnttab_map_shared(frames, nr_gframes,
595 gnttab_max_grant_frames(),
596 &gnttab_shared.addr);
597 BUG_ON(rc);
598
599 return 0;
600}
601
602static void gnttab_unmap_frames_v1(void)
603{
604 arch_gnttab_unmap_shared(gnttab_shared.addr, nr_grant_frames);
605}
606
523static int gnttab_map(unsigned int start_idx, unsigned int end_idx) 607static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
524{ 608{
525 struct gnttab_setup_table setup; 609 struct gnttab_setup_table setup;
@@ -567,19 +651,35 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
567 651
568 BUG_ON(rc || setup.status); 652 BUG_ON(rc || setup.status);
569 653
570 rc = arch_gnttab_map_shared(frames, nr_gframes, gnttab_max_grant_frames(), 654 rc = gnttab_interface->map_frames(frames, nr_gframes);
571 &shared);
572 BUG_ON(rc);
573 655
574 kfree(frames); 656 kfree(frames);
575 657
576 return 0; 658 return rc;
659}
660
661static struct gnttab_ops gnttab_v1_ops = {
662 .map_frames = gnttab_map_frames_v1,
663 .unmap_frames = gnttab_unmap_frames_v1,
664 .update_entry = gnttab_update_entry_v1,
665 .end_foreign_access_ref = gnttab_end_foreign_access_ref_v1,
666 .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v1,
667 .query_foreign_access = gnttab_query_foreign_access_v1,
668};
669
670static void gnttab_request_version(void)
671{
672 grant_table_version = 1;
673 gnttab_interface = &gnttab_v1_ops;
674 printk(KERN_INFO "Grant tables using version %d layout.\n",
675 grant_table_version);
577} 676}
578 677
579int gnttab_resume(void) 678int gnttab_resume(void)
580{ 679{
581 unsigned int max_nr_gframes; 680 unsigned int max_nr_gframes;
582 681
682 gnttab_request_version();
583 max_nr_gframes = gnttab_max_grant_frames(); 683 max_nr_gframes = gnttab_max_grant_frames();
584 if (max_nr_gframes < nr_grant_frames) 684 if (max_nr_gframes < nr_grant_frames)
585 return -ENOSYS; 685 return -ENOSYS;
@@ -587,9 +687,10 @@ int gnttab_resume(void)
587 if (xen_pv_domain()) 687 if (xen_pv_domain())
588 return gnttab_map(0, nr_grant_frames - 1); 688 return gnttab_map(0, nr_grant_frames - 1);
589 689
590 if (!shared) { 690 if (gnttab_shared.addr == NULL) {
591 shared = ioremap(xen_hvm_resume_frames, PAGE_SIZE * max_nr_gframes); 691 gnttab_shared.addr = ioremap(xen_hvm_resume_frames,
592 if (shared == NULL) { 692 PAGE_SIZE * max_nr_gframes);
693 if (gnttab_shared.addr == NULL) {
593 printk(KERN_WARNING 694 printk(KERN_WARNING
594 "Failed to ioremap gnttab share frames!"); 695 "Failed to ioremap gnttab share frames!");
595 return -ENOMEM; 696 return -ENOMEM;
@@ -603,7 +704,7 @@ int gnttab_resume(void)
603 704
604int gnttab_suspend(void) 705int gnttab_suspend(void)
605{ 706{
606 arch_gnttab_unmap_shared(shared, nr_grant_frames); 707 gnttab_interface->unmap_frames();
607 return 0; 708 return 0;
608} 709}
609 710