Skip to content

Commit

Permalink
xen/grant: Introduce helpers to split a page into grant
Browse files Browse the repository at this point in the history
Currently, a grant is always based on the Xen page granularity (i.e
4KB). When Linux is using a different page granularity, a single page
will be split between multiple grants.

The new helpers will be in charge of splitting the Linux page into grants
and call a function given by the caller on each grant.

Also provide an helper to count the number of grants within a given
contiguous region.

Note that the x86/include/asm/xen/page.h is now including
xen/interface/grant_table.h rather than xen/grant_table.h. It's
necessary because xen/grant_table.h depends on asm/xen/page.h and will
break the compilation. Furthermore, only definition in
interface/grant_table.h is required.

Signed-off-by: Julien Grall <[email protected]>
Reviewed-by: David Vrabel <[email protected]>
Reviewed-by: Stefano Stabellini <[email protected]>
Signed-off-by: David Vrabel <[email protected]>
  • Loading branch information
Julien Grall authored and David Vrabel committed Oct 23, 2015
1 parent 1084b19 commit 008c320
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 1 deletion.
2 changes: 1 addition & 1 deletion arch/x86/include/asm/xen/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <asm/pgtable.h>

#include <xen/interface/xen.h>
#include <xen/grant_table.h>
#include <xen/interface/grant_table.h>
#include <xen/features.h>

/* Xen machine address */
Expand Down
26 changes: 26 additions & 0 deletions drivers/xen/grant-table.c
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,32 @@ void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count)
}
EXPORT_SYMBOL_GPL(gnttab_batch_copy);

void gnttab_foreach_grant_in_range(struct page *page,
unsigned int offset,
unsigned int len,
xen_grant_fn_t fn,
void *data)
{
unsigned int goffset;
unsigned int glen;
unsigned long xen_pfn;

len = min_t(unsigned int, PAGE_SIZE - offset, len);
goffset = xen_offset_in_page(offset);

xen_pfn = page_to_xen_pfn(page) + XEN_PFN_DOWN(offset);

while (len) {
glen = min_t(unsigned int, XEN_PAGE_SIZE - goffset, len);
fn(pfn_to_gfn(xen_pfn), goffset, glen, data);

goffset = 0;
xen_pfn++;
len -= glen;
}
}
EXPORT_SYMBOL_GPL(gnttab_foreach_grant_in_range);

int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
struct gnttab_map_grant_ref *kmap_ops,
struct page **pages, unsigned int count)
Expand Down
42 changes: 42 additions & 0 deletions include/xen/grant_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@
#include <asm/xen/hypervisor.h>

#include <xen/features.h>
#include <xen/page.h>
#include <linux/mm_types.h>
#include <linux/page-flags.h>
#include <linux/kernel.h>

#define GNTTAB_RESERVED_XENSTORE 1

Expand Down Expand Up @@ -224,4 +226,44 @@ static inline struct xen_page_foreign *xen_page_foreign(struct page *page)
#endif
}

/* Split Linux page in chunk of the size of the grant and call fn
*
* Parameters of fn:
* gfn: guest frame number
* offset: offset in the grant
* len: length of the data in the grant.
* data: internal information
*/
typedef void (*xen_grant_fn_t)(unsigned long gfn, unsigned int offset,
unsigned int len, void *data);

void gnttab_foreach_grant_in_range(struct page *page,
unsigned int offset,
unsigned int len,
xen_grant_fn_t fn,
void *data);

/* Helper to get to call fn only on the first "grant chunk" */
static inline void gnttab_for_one_grant(struct page *page, unsigned int offset,
unsigned len, xen_grant_fn_t fn,
void *data)
{
/* The first request is limited to the size of one grant */
len = min_t(unsigned int, XEN_PAGE_SIZE - (offset & ~XEN_PAGE_MASK),
len);

gnttab_foreach_grant_in_range(page, offset, len, fn, data);
}

/* Get the number of grant in a specified region
*
* start: Offset from the beginning of the first page
* len: total length of data (can cross multiple page)
*/
static inline unsigned int gnttab_count_grant(unsigned int start,
unsigned int len)
{
return XEN_PFN_UP(xen_offset_in_page(start) + len);
}

#endif /* __ASM_GNTTAB_H__ */

0 comments on commit 008c320

Please sign in to comment.