diff options
author | Annie Li <annie.li@oracle.com> | 2011-12-12 05:15:07 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-12-16 11:25:39 -0500 |
commit | 9438ce9dbbf512fd717051284f568d5cb35e5cf1 (patch) | |
tree | 53c2abe7dccbf557586cb04319a0f9c6eed3a317 /drivers/xen | |
parent | 6666754b11297526c699f8df63c52d50c24fe946 (diff) |
xen/granttable: Support transitive grants
These allow a domain A which has been granted access on a page of domain B's
memory to issue domain C with a copy-grant on the same page. This is useful
e.g. for forwarding packets between domains.
Signed-off-by: Annie Li <annie.li@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen')
-rw-r--r-- | drivers/xen/grant-table.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index c8312c7056f1..a3d0e1e278c1 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -131,6 +131,18 @@ struct gnttab_ops { | |||
131 | void (*update_subpage_entry)(grant_ref_t ref, domid_t domid, | 131 | void (*update_subpage_entry)(grant_ref_t ref, domid_t domid, |
132 | unsigned long frame, int flags, | 132 | unsigned long frame, int flags, |
133 | unsigned page_off, unsigned length); | 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); | ||
134 | }; | 146 | }; |
135 | 147 | ||
136 | static struct gnttab_ops *gnttab_interface; | 148 | static struct gnttab_ops *gnttab_interface; |
@@ -332,6 +344,63 @@ bool gnttab_subpage_grants_available(void) | |||
332 | } | 344 | } |
333 | EXPORT_SYMBOL_GPL(gnttab_subpage_grants_available); | 345 | EXPORT_SYMBOL_GPL(gnttab_subpage_grants_available); |
334 | 346 | ||
347 | 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 | |||
359 | int 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 | } | ||
375 | EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_trans_ref); | ||
376 | |||
377 | int 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 | } | ||
396 | EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_trans); | ||
397 | |||
398 | bool gnttab_trans_grants_available(void) | ||
399 | { | ||
400 | return gnttab_interface->update_trans_entry != NULL; | ||
401 | } | ||
402 | EXPORT_SYMBOL_GPL(gnttab_trans_grants_available); | ||
403 | |||
335 | static int gnttab_query_foreign_access_v1(grant_ref_t ref) | 404 | static int gnttab_query_foreign_access_v1(grant_ref_t ref) |
336 | { | 405 | { |
337 | return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing); | 406 | return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing); |
@@ -885,6 +954,7 @@ static struct gnttab_ops gnttab_v2_ops = { | |||
885 | .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v2, | 954 | .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v2, |
886 | .query_foreign_access = gnttab_query_foreign_access_v2, | 955 | .query_foreign_access = gnttab_query_foreign_access_v2, |
887 | .update_subpage_entry = gnttab_update_subpage_entry_v2, | 956 | .update_subpage_entry = gnttab_update_subpage_entry_v2, |
957 | .update_trans_entry = gnttab_update_trans_entry_v2, | ||
888 | }; | 958 | }; |
889 | 959 | ||
890 | static void gnttab_request_version(void) | 960 | static void gnttab_request_version(void) |