Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9438ce9d authored by Annie Li's avatar Annie Li Committed by Konrad Rzeszutek Wilk
Browse files

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: default avatarAnnie Li <annie.li@oracle.com>
Signed-off-by: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
parent 6666754b
Loading
Loading
Loading
Loading
+70 −0
Original line number Diff line number Diff line
@@ -131,6 +131,18 @@ struct gnttab_ops {
	void (*update_subpage_entry)(grant_ref_t ref, domid_t domid,
				     unsigned long frame, int flags,
				     unsigned page_off, unsigned length);
	/*
	 * Redirect an available grant entry on domain A to another grant
	 * reference of domain B, then allow domain C to use grant reference
	 * of domain B transitively. Ref parameter is an available grant entry
	 * reference on domain A, domid is id of domain C which accesses grant
	 * entry transitively, flags is grant type and flag information,
	 * trans_domid is id of domain B whose grant entry is finally accessed
	 * transitively, trans_gref is grant entry transitive reference of
	 * domain B.
	 */
	void (*update_trans_entry)(grant_ref_t ref, domid_t domid, int flags,
				   domid_t trans_domid, grant_ref_t trans_gref);
};

static struct gnttab_ops *gnttab_interface;
@@ -332,6 +344,63 @@ bool gnttab_subpage_grants_available(void)
}
EXPORT_SYMBOL_GPL(gnttab_subpage_grants_available);

void gnttab_update_trans_entry_v2(grant_ref_t ref, domid_t domid,
				  int flags, domid_t trans_domid,
				  grant_ref_t trans_gref)
{
	gnttab_shared.v2[ref].transitive.trans_domid = trans_domid;
	gnttab_shared.v2[ref].transitive.gref = trans_gref;
	gnttab_shared.v2[ref].hdr.domid = domid;
	wmb();
	gnttab_shared.v2[ref].hdr.flags =
				GTF_permit_access | GTF_transitive | flags;
}

int gnttab_grant_foreign_access_trans_ref(grant_ref_t ref, domid_t domid,
					  int flags, domid_t trans_domid,
					  grant_ref_t trans_gref)
{
	if (flags & (GTF_accept_transfer | GTF_reading |
		     GTF_writing | GTF_sub_page))
		return -EPERM;

	if (gnttab_interface->update_trans_entry == NULL)
		return -ENOSYS;

	gnttab_interface->update_trans_entry(ref, domid, flags, trans_domid,
					     trans_gref);

	return 0;
}
EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_trans_ref);

int gnttab_grant_foreign_access_trans(domid_t domid, int flags,
				      domid_t trans_domid,
				      grant_ref_t trans_gref)
{
	int ref, rc;

	ref = get_free_entries(1);
	if (unlikely(ref < 0))
		return -ENOSPC;

	rc = gnttab_grant_foreign_access_trans_ref(ref, domid, flags,
						   trans_domid, trans_gref);
	if (rc < 0) {
		put_free_entry(ref);
		return rc;
	}

	return ref;
}
EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_trans);

bool gnttab_trans_grants_available(void)
{
	return gnttab_interface->update_trans_entry != NULL;
}
EXPORT_SYMBOL_GPL(gnttab_trans_grants_available);

static int gnttab_query_foreign_access_v1(grant_ref_t ref)
{
	return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing);
@@ -885,6 +954,7 @@ static struct gnttab_ops gnttab_v2_ops = {
	.end_foreign_transfer_ref	= gnttab_end_foreign_transfer_ref_v2,
	.query_foreign_access		= gnttab_query_foreign_access_v2,
	.update_subpage_entry		= gnttab_update_subpage_entry_v2,
	.update_trans_entry		= gnttab_update_trans_entry_v2,
};

static void gnttab_request_version(void)
+12 −0
Original line number Diff line number Diff line
@@ -65,6 +65,9 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
int gnttab_grant_foreign_access_subpage(domid_t domid, unsigned long frame,
					int flags, unsigned page_off,
					unsigned length);
int gnttab_grant_foreign_access_trans(domid_t domid, int flags,
				      domid_t trans_domid,
				      grant_ref_t trans_gref);

/*
 * Are sub-page grants available on this version of Xen?  Returns true if they
@@ -72,6 +75,12 @@ int gnttab_grant_foreign_access_subpage(domid_t domid, unsigned long frame,
 */
bool gnttab_subpage_grants_available(void);

/*
 * Are transitive grants available on this version of Xen?  Returns true if they
 * are, and false if they're not.
 */
bool gnttab_trans_grants_available(void);

/*
 * End access through the given grant reference, iff the grant entry is no
 * longer in use.  Return 1 if the grant entry was freed, 0 if it is still in
@@ -121,6 +130,9 @@ int gnttab_grant_foreign_access_subpage_ref(grant_ref_t ref, domid_t domid,
					    unsigned long frame, int flags,
					    unsigned page_off,
					    unsigned length);
int gnttab_grant_foreign_access_trans_ref(grant_ref_t ref, domid_t domid,
					  int flags, domid_t trans_domid,
					  grant_ref_t trans_gref);

void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
				       unsigned long pfn);