xen: mark grant mapped pages as foreign

Use the "foreign" page flag to mark pages that have a grant map.  Use
page->private to store information of the grant (the granting domain
and the grant reference).

Signed-off-by: Jennifer Herbert <jennifer.herbert@citrix.com>
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
This commit is contained in:
Jennifer Herbert 2014-12-24 14:17:06 +00:00 committed by David Vrabel
parent ff4b156f16
commit 8da7633f16
3 changed files with 61 additions and 9 deletions

View file

@ -681,12 +681,8 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
} }
pfn = page_to_pfn(pages[i]); pfn = page_to_pfn(pages[i]);
WARN_ON(PagePrivate(pages[i]));
WARN(pfn_to_mfn(pfn) != INVALID_P2M_ENTRY, "page must be ballooned"); WARN(pfn_to_mfn(pfn) != INVALID_P2M_ENTRY, "page must be ballooned");
SetPagePrivate(pages[i]);
set_page_private(pages[i], mfn);
if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) { if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
@ -716,9 +712,6 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
goto out; goto out;
} }
set_page_private(pages[i], INVALID_P2M_ENTRY);
WARN_ON(!PagePrivate(pages[i]));
ClearPagePrivate(pages[i]);
set_phys_to_machine(pfn, INVALID_P2M_ENTRY); set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
} }
if (kunmap_ops) if (kunmap_ops)

View file

@ -679,12 +679,27 @@ EXPORT_SYMBOL_GPL(gnttab_free_auto_xlat_frames);
*/ */
int gnttab_alloc_pages(int nr_pages, struct page **pages) int gnttab_alloc_pages(int nr_pages, struct page **pages)
{ {
int i;
int ret; int ret;
ret = alloc_xenballooned_pages(nr_pages, pages, false); ret = alloc_xenballooned_pages(nr_pages, pages, false);
if (ret < 0) if (ret < 0)
return ret; return ret;
for (i = 0; i < nr_pages; i++) {
#if BITS_PER_LONG < 64
struct xen_page_foreign *foreign;
foreign = kzalloc(sizeof(*foreign), GFP_KERNEL);
if (!foreign) {
gnttab_free_pages(nr_pages, pages);
return -ENOMEM;
}
set_page_private(pages[i], (unsigned long)foreign);
#endif
SetPagePrivate(pages[i]);
}
return 0; return 0;
} }
EXPORT_SYMBOL(gnttab_alloc_pages); EXPORT_SYMBOL(gnttab_alloc_pages);
@ -696,6 +711,16 @@ EXPORT_SYMBOL(gnttab_alloc_pages);
*/ */
void gnttab_free_pages(int nr_pages, struct page **pages) void gnttab_free_pages(int nr_pages, struct page **pages)
{ {
int i;
for (i = 0; i < nr_pages; i++) {
if (PagePrivate(pages[i])) {
#if BITS_PER_LONG < 64
kfree((void *)page_private(pages[i]));
#endif
ClearPagePrivate(pages[i]);
}
}
free_xenballooned_pages(nr_pages, pages); free_xenballooned_pages(nr_pages, pages);
} }
EXPORT_SYMBOL(gnttab_free_pages); EXPORT_SYMBOL(gnttab_free_pages);
@ -756,12 +781,22 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
if (ret) if (ret)
return ret; return ret;
/* Retry eagain maps */ for (i = 0; i < count; i++) {
for (i = 0; i < count; i++) /* Retry eagain maps */
if (map_ops[i].status == GNTST_eagain) if (map_ops[i].status == GNTST_eagain)
gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i, gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i,
&map_ops[i].status, __func__); &map_ops[i].status, __func__);
if (map_ops[i].status == GNTST_okay) {
struct xen_page_foreign *foreign;
SetPageForeign(pages[i]);
foreign = xen_page_foreign(pages[i]);
foreign->domid = map_ops[i].dom;
foreign->gref = map_ops[i].ref;
}
}
return set_foreign_p2m_mapping(map_ops, kmap_ops, pages, count); return set_foreign_p2m_mapping(map_ops, kmap_ops, pages, count);
} }
EXPORT_SYMBOL_GPL(gnttab_map_refs); EXPORT_SYMBOL_GPL(gnttab_map_refs);
@ -770,12 +805,16 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
struct gnttab_unmap_grant_ref *kunmap_ops, struct gnttab_unmap_grant_ref *kunmap_ops,
struct page **pages, unsigned int count) struct page **pages, unsigned int count)
{ {
unsigned int i;
int ret; int ret;
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count); ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count);
if (ret) if (ret)
return ret; return ret;
for (i = 0; i < count; i++)
ClearPageForeign(pages[i]);
return clear_foreign_p2m_mapping(unmap_ops, kunmap_ops, pages, count); return clear_foreign_p2m_mapping(unmap_ops, kunmap_ops, pages, count);
} }
EXPORT_SYMBOL_GPL(gnttab_unmap_refs); EXPORT_SYMBOL_GPL(gnttab_unmap_refs);

View file

@ -45,6 +45,8 @@
#include <asm/xen/hypervisor.h> #include <asm/xen/hypervisor.h>
#include <xen/features.h> #include <xen/features.h>
#include <linux/mm_types.h>
#include <linux/page-flags.h>
#define GNTTAB_RESERVED_XENSTORE 1 #define GNTTAB_RESERVED_XENSTORE 1
@ -185,4 +187,22 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count); void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count);
void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count); void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count);
struct xen_page_foreign {
domid_t domid;
grant_ref_t gref;
};
static inline struct xen_page_foreign *xen_page_foreign(struct page *page)
{
if (!PageForeign(page))
return NULL;
#if BITS_PER_LONG < 64
return (struct xen_page_foreign *)page->private;
#else
BUILD_BUG_ON(sizeof(struct xen_page_foreign) > BITS_PER_LONG);
return (struct xen_page_foreign *)&page->private;
#endif
}
#endif /* __ASM_GNTTAB_H__ */ #endif /* __ASM_GNTTAB_H__ */