xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
To: "ruozeng.w" <ruozeng.w@gmail.com>
Cc: xen-devel <xen-devel@lists.xensource.com>
Subject: Re: How can I use grant table in domainU?
Date: Mon, 4 Apr 2011 10:25:26 -0400	[thread overview]
Message-ID: <20110404142526.GB9182@dumpdata.com> (raw)
In-Reply-To: <201104041815185384477@gmail.com>

On Mon, Apr 04, 2011 at 06:15:22PM +0800, ruozeng.w wrote:
> Can applications runs in domainU use grant table?
> 
> I found a way in the document(/docs/misc/grant-tables.txt), using function gnttab_grant_foreign_access . But, this fucntion is defined in domainU kernel, for example, in my installation, it's in /linux-2.6.18-xen.hg/include/xen/gnttab.h. 
> 
> Then how can I call this function in my own application? 
> If I wants to write a simple program(program1) runs in domainA, to map a frame to domainB, in which another simple program(program2) is running, then program2 can read the information program1 sent to domainB, what should I do?

Get 2.6.39 and use /dev/gntdev, /dev/gntalloc to do so. Attached is a test program
written by Daniel De Graaf.


#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

struct ioctl_gntdev_grant_ref {
	/* The domain ID of the grant to be mapped. */
	uint32_t domid;
	/* The grant reference of the grant to be mapped. */
	uint32_t ref;
};

/*
 * Allocates a new page and creates a new grant reference.
 */
#define IOCTL_GNTALLOC_ALLOC_GREF \
_IOC(_IOC_NONE, 'G', 5, sizeof(struct ioctl_gntalloc_alloc_gref))
struct ioctl_gntalloc_alloc_gref {
	/* IN parameters */
	/* The ID of the domain to be given access to the grants. */
	uint16_t domid;
	/* Flags for this mapping */
	uint16_t flags;
	/* Number of pages to map */
	uint32_t count;
	/* OUT parameters */
	/* The offset to be used on a subsequent call to mmap(). */
	uint64_t index;
	/* The grant references of the newly created grant, one per page */
	/* Variable size, depending on count */
	uint32_t gref_ids[1];
};

#define GNTALLOC_FLAG_WRITABLE 1

/*
 * Deallocates the grant reference, allowing the associated page to be freed if
 * no other domains are using it.
 */
#define IOCTL_GNTALLOC_DEALLOC_GREF \
_IOC(_IOC_NONE, 'G', 6, sizeof(struct ioctl_gntalloc_dealloc_gref))
struct ioctl_gntalloc_dealloc_gref {
	/* IN parameters */
	/* The offset returned in the map operation */
	uint64_t index;
	/* Number of references to unmap */
	uint32_t count;
};

#define IOCTL_GNTDEV_MAP_GRANT_REF \
_IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_gntdev_map_grant_ref))
struct ioctl_gntdev_map_grant_ref {
    /* IN parameters */
    /* The number of grants to be mapped. */
    uint32_t count;
    uint32_t pad;
    /* OUT parameters */
    /* The offset to be used on a subsequent call to mmap(). */
    uint64_t index;
    /* Variable IN parameter. */
    /* Array of grant references, of size @count. */
    struct ioctl_gntdev_grant_ref refs[1];
};
#define GNTDEV_MAP_WRITABLE 0x1

#define IOCTL_GNTDEV_UNMAP_GRANT_REF \
_IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_gntdev_unmap_grant_ref))       
struct ioctl_gntdev_unmap_grant_ref {
    /* IN parameters */
    /* The offset was returned by the corresponding map operation. */
    uint64_t index;
    /* The number of pages to be unmapped. */
    uint32_t count;
    uint32_t pad;
};

/*
 * Sets up an unmap notification within the page, so that the other side can do
 * cleanup if this side crashes. Required to implement cross-domain robust
 * mutexes or close notification on communication channels.
 *
 * Each mapped page only supports one notification; multiple calls referring to
 * the same page overwrite the previous notification. You must clear the
 * notification prior to the IOCTL_GNTALLOC_DEALLOC_GREF if you do not want it
 * to occur.
 */
#define IOCTL_GNTDEV_SET_UNMAP_NOTIFY \
_IOC(_IOC_NONE, 'G', 7, sizeof(struct ioctl_gntdev_unmap_notify))
struct ioctl_gntdev_unmap_notify {
	/* IN parameters */
	/* Index of a byte in the page */
	uint64_t index;
	/* Action(s) to take on unmap */
	uint32_t action;
	/* Event channel to notify */
	uint32_t event_channel_port;
};

/* Clear (set to zero) the byte specified by index */
#define UNMAP_NOTIFY_CLEAR_BYTE 0x1
/* Send an interrupt on the indicated event channel */
#define UNMAP_NOTIFY_SEND_EVENT 0x2

/*
 * Sets up an unmap notification within the page, so that the other side can do
 * cleanup if this side crashes. Required to implement cross-domain robust
 * mutexes or close notification on communication channels.
 *
 * Each mapped page only supports one notification; multiple calls referring to
 * the same page overwrite the previous notification. You must clear the
 * notification prior to the IOCTL_GNTALLOC_DEALLOC_GREF if you do not want it
 * to occur.
 */
#define IOCTL_GNTALLOC_SET_UNMAP_NOTIFY \
_IOC(_IOC_NONE, 'G', 7, sizeof(struct ioctl_gntalloc_unmap_notify))
struct ioctl_gntalloc_unmap_notify {
	/* IN parameters */
	/* Index of a byte in the page */
	uint64_t index;
	/* Action(s) to take on unmap */
	uint32_t action;
	/* Event channel to notify */
	uint32_t event_channel_port;
};

/* Clear (set to zero) the byte specified by index */
#define UNMAP_NOTIFY_CLEAR_BYTE 0x1
/* Send an interrupt on the indicated event channel */
#define UNMAP_NOTIFY_SEND_EVENT 0x2

#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif


int a_fd;
int d_fd;

struct shr_page {
	uint64_t id;
	char buffer[64];
	uint8_t notifies[8];
};

struct data {
	struct shr_page* mem;
	int handle;
} items[128];

void sa(int id)
{
	struct ioctl_gntalloc_alloc_gref arg = {
		.domid = id,
		.flags = GNTALLOC_FLAG_WRITABLE,
		.count = 1
	};
	int rv = ioctl(a_fd, IOCTL_GNTALLOC_ALLOC_GREF, &arg);
	if (rv) {
		printf("src-add error: %s (rv=%d)\n", strerror(errno), rv);
		return;
	}
	int i=0;
	while (items[i].mem) i++;
	items[i].mem = mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, a_fd, arg.index);
	if (items[i].mem == MAP_FAILED) {
		items[i].mem = 0;
		printf("mmap failed: SHOULD NOT HAPPEN\n");
		return;
	}
	items[i].handle = arg.index;
	printf("Created shared page with domain %d, grant #%d. Mapped locally at %d=%p\n",
		id, arg.gref_ids[0], arg.index, items[i].mem);

	items[i].mem->id = rand() | ((long)(getpid()) << 32);
	items[i].mem->notifies[0] = 1;
	struct ioctl_gntalloc_unmap_notify uarg = {
		.index = arg.index + offsetof(struct shr_page, notifies[0]),
		.action = UNMAP_NOTIFY_CLEAR_BYTE
	};
	rv = ioctl(a_fd, IOCTL_GNTALLOC_SET_UNMAP_NOTIFY, &uarg);
	if (rv)
		printf("gntalloc unmap notify error: %s (rv=%d)\n", strerror(errno), rv);
}

void sd(int ref) {
	struct ioctl_gntalloc_dealloc_gref arg = {
		.index = ref,
		.count = 1
	};

	int rv = ioctl(a_fd, IOCTL_GNTALLOC_DEALLOC_GREF, &arg);
	if (rv)
		printf("src-del error: %s (rv=%d)\n", strerror(errno), rv);
	else
		printf("Stopped offering grant at offset %d\n", ref);
}

void mm(int domid, int refid) {
	struct ioctl_gntdev_map_grant_ref arg = {
		.count = 1,
		.refs[0].domid = domid,
		.refs[0].ref = refid,
	};
	int rv = ioctl(d_fd, IOCTL_GNTDEV_MAP_GRANT_REF, &arg);
	if (rv) {
		printf("Could not map grant %d.%d: %s (rv=%d)\n", domid, refid, strerror(errno), rv);
		return;
	}
	int i=0,j=1;
	while (items[i].mem) i++;
	items[i].mem = mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, d_fd, arg.index);
	if (items[i].mem == MAP_FAILED) {
		items[i].mem = 0;
		printf("Could not map grant %d.%d: %s (map failed)\n", domid, refid, strerror(errno), rv);
		return;
	}
	items[i].handle = arg.index;
	printf("Mapped grant %d.%d as %d=%p\n", domid, refid, arg.index, items[i].mem);

	while (items[i].mem->notifies[j]) j++;
	items[i].mem->notifies[j] = 1;
	struct ioctl_gntalloc_unmap_notify uarg = {
		.index = arg.index + offsetof(struct shr_page, notifies[j]),
		.action = UNMAP_NOTIFY_CLEAR_BYTE
	};
	rv = ioctl(d_fd, IOCTL_GNTDEV_SET_UNMAP_NOTIFY, &uarg);
	if (rv)
		printf("gntdev unmap notify error: %s (rv=%d)\n", strerror(errno), rv);
}

void gu(int index) {
	struct ioctl_gntdev_unmap_grant_ref arg = {
		.index = index,
		.count = 1,
	};
	int rv = ioctl(d_fd, IOCTL_GNTDEV_UNMAP_GRANT_REF, &arg);
	if (rv)
		printf("gu error: %s (rv=%d)\n", strerror(errno), rv);
	else
		printf("Unhooked mapped grant at offset %d\n", index);
}

void mu(void* addr) {
	int i = 0;
	munmap(addr, 4096);
	while (i < 128)
	{
		if (items[i].mem == addr)
			items[i].mem = 0;
		i++;
	}
	printf("Unmapped page at %p\n", addr);
}

void show(char* word) {
	int i;
	int wlen = strlen(word);
	for(i=0; i < 128; i++) {
		if (!items[i].mem)
			continue;
		memmove(items[i].mem->buffer + wlen, items[i].mem->buffer, 63 - wlen);
		memcpy(items[i].mem->buffer, word, wlen);
		printf("%02d(%ld,%d): id %16lx n=%d%d%d%d%d%d%d%d b=%s\n",
			i, items[i].mem, items[i].handle, items[i].mem->id,
			items[i].mem->notifies[0], items[i].mem->notifies[1], items[i].mem->notifies[2], items[i].mem->notifies[3], 
			items[i].mem->notifies[4], items[i].mem->notifies[5], items[i].mem->notifies[6], items[i].mem->notifies[7], 
			items[i].mem->buffer);
	}
	printf("END\n");
}

int main(int argc, char** argv) {
	a_fd = open("/dev/xen/gntalloc", O_RDWR);
	d_fd = open("/dev/xen/gntdev", O_RDWR);
	printf(
		"add <domid>           return gntref, address\n"
		"map <domid> <ref>     return index, address\n"
		"adel <gntref>         delete <add> internal\n"
		"ddel <index>          delete <map> internal\n"
		"unmap <address>       unmap memory\n"
		"show                  show all pages\n"
		"<word>                append word to all mapped pages, show\n"
		" PID %x\n", getpid()
	);
	while (1) {
		char line[80];
		char word[80];
		long a, b;
		printf("\n> ");
		fflush(stdout);
		fgets(line, 80, stdin);
		sscanf(line, "%s %ld %ld", word, &a, &b);
		if (!strcmp(word, "add")) {
			sa(a);
		} else if (!strcmp(word, "map")) {
			mm(a, b);
		} else if (!strcmp(word, "adel")) {
			sd(a);
		} else if (!strcmp(word, "ddel")) {
			gu(a);
		} else if (!strcmp(word, "unmap")) {
			mu((void*)a);
		} else if (!strcmp(word, "show")) {
			show("");
		} else {
			show(word);
		}
	}
}
> 
> thanks.
> 
> 2011-04-04 
> 
> 
> 
> Wishes
> Ruozeng W 

> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel

  reply	other threads:[~2011-04-04 14:25 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-04 10:15 How can I use grant table in domainU? ruozeng.w
2011-04-04 14:25 ` Konrad Rzeszutek Wilk [this message]
     [not found] ` <201104051205497648564@gmail.com>
     [not found]   ` <20110405134423.GA6075@dumpdata.com>
     [not found]     ` <BANLkTinkrAr9cKb17skdtWdQTJ1AT63xCA@mail.gmail.com>
     [not found]       ` <20110406121510.GA5009@dumpdata.com>
     [not found]         ` <BANLkTikHJ5TtiOZOc7mdLpMqg-s4OmMBEA@mail.gmail.com>
     [not found]           ` <20110406152554.GA8253@dumpdata.com>
     [not found]             ` <BANLkTi=0fEdC8PjsWp_8rmdwybpsex1q+Q@mail.gmail.com>
2011-04-13 17:43               ` Konrad Rzeszutek Wilk
2011-04-14  2:08                 ` ruozeng wang
2011-04-14 12:22                   ` ruozeng wang
2011-04-14 13:39                     ` Konrad Rzeszutek Wilk
2011-04-14 15:58                       ` ruozeng wang
2011-04-14 16:20                         ` Re: Xend hanging Konrad Rzeszutek Wilk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110404142526.GB9182@dumpdata.com \
    --to=konrad.wilk@oracle.com \
    --cc=ruozeng.w@gmail.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).