diff options
Diffstat (limited to 'drivers/xen/grant-table.c')
-rw-r--r-- | drivers/xen/grant-table.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 6c4531816496..fd725cde6ad1 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -447,6 +447,79 @@ unsigned int gnttab_max_grant_frames(void) | |||
447 | } | 447 | } |
448 | EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); | 448 | EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); |
449 | 449 | ||
450 | int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, | ||
451 | struct page **pages, unsigned int count) | ||
452 | { | ||
453 | int i, ret; | ||
454 | pte_t *pte; | ||
455 | unsigned long mfn; | ||
456 | |||
457 | ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count); | ||
458 | if (ret) | ||
459 | return ret; | ||
460 | |||
461 | if (xen_feature(XENFEAT_auto_translated_physmap)) | ||
462 | return ret; | ||
463 | |||
464 | for (i = 0; i < count; i++) { | ||
465 | /* Do not add to override if the map failed. */ | ||
466 | if (map_ops[i].status) | ||
467 | continue; | ||
468 | |||
469 | if (map_ops[i].flags & GNTMAP_contains_pte) { | ||
470 | pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) + | ||
471 | (map_ops[i].host_addr & ~PAGE_MASK)); | ||
472 | mfn = pte_mfn(*pte); | ||
473 | } else { | ||
474 | /* If you really wanted to do this: | ||
475 | * mfn = PFN_DOWN(map_ops[i].dev_bus_addr); | ||
476 | * | ||
477 | * The reason we do not implement it is b/c on the | ||
478 | * unmap path (gnttab_unmap_refs) we have no means of | ||
479 | * checking whether the page is !GNTMAP_contains_pte. | ||
480 | * | ||
481 | * That is without some extra data-structure to carry | ||
482 | * the struct page, bool clear_pte, and list_head next | ||
483 | * tuples and deal with allocation/delallocation, etc. | ||
484 | * | ||
485 | * The users of this API set the GNTMAP_contains_pte | ||
486 | * flag so lets just return not supported until it | ||
487 | * becomes neccessary to implement. | ||
488 | */ | ||
489 | return -EOPNOTSUPP; | ||
490 | } | ||
491 | ret = m2p_add_override(mfn, pages[i], | ||
492 | map_ops[i].flags & GNTMAP_contains_pte); | ||
493 | if (ret) | ||
494 | return ret; | ||
495 | } | ||
496 | |||
497 | return ret; | ||
498 | } | ||
499 | EXPORT_SYMBOL_GPL(gnttab_map_refs); | ||
500 | |||
501 | int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, | ||
502 | struct page **pages, unsigned int count) | ||
503 | { | ||
504 | int i, ret; | ||
505 | |||
506 | ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count); | ||
507 | if (ret) | ||
508 | return ret; | ||
509 | |||
510 | if (xen_feature(XENFEAT_auto_translated_physmap)) | ||
511 | return ret; | ||
512 | |||
513 | for (i = 0; i < count; i++) { | ||
514 | ret = m2p_remove_override(pages[i], true /* clear the PTE */); | ||
515 | if (ret) | ||
516 | return ret; | ||
517 | } | ||
518 | |||
519 | return ret; | ||
520 | } | ||
521 | EXPORT_SYMBOL_GPL(gnttab_unmap_refs); | ||
522 | |||
450 | static int gnttab_map(unsigned int start_idx, unsigned int end_idx) | 523 | static int gnttab_map(unsigned int start_idx, unsigned int end_idx) |
451 | { | 524 | { |
452 | struct gnttab_setup_table setup; | 525 | struct gnttab_setup_table setup; |