xen_backend: add grant table helpers
This patch adds grant table helper functions to the xen_backend code to localize error reporting and use of xen_domid. The patch also defers the call to xengnttab_open() until just before the initialise method in XenDevOps is invoked. This method is responsible for mapping the shared ring. No prior method requires access to the grant table. Signed-off-by: Paul Durrant <paul.durrant@citrix.com> Acked-by: Anthony PERARD <anthony.perard@citrix.com> Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
This commit is contained in:
parent
5c0d914a9b
commit
9838824aff
@ -106,6 +106,103 @@ int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void xen_be_set_max_grant_refs(struct XenDevice *xendev,
|
||||
unsigned int nr_refs)
|
||||
{
|
||||
assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
|
||||
|
||||
if (xengnttab_set_max_grants(xendev->gnttabdev, nr_refs)) {
|
||||
xen_pv_printf(xendev, 0, "xengnttab_set_max_grants failed: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void *xen_be_map_grant_refs(struct XenDevice *xendev, uint32_t *refs,
|
||||
unsigned int nr_refs, int prot)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
|
||||
|
||||
ptr = xengnttab_map_domain_grant_refs(xendev->gnttabdev, nr_refs,
|
||||
xen_domid, refs, prot);
|
||||
if (!ptr) {
|
||||
xen_pv_printf(xendev, 0,
|
||||
"xengnttab_map_domain_grant_refs failed: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void xen_be_unmap_grant_refs(struct XenDevice *xendev, void *ptr,
|
||||
unsigned int nr_refs)
|
||||
{
|
||||
assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
|
||||
|
||||
if (xengnttab_unmap(xendev->gnttabdev, ptr, nr_refs)) {
|
||||
xen_pv_printf(xendev, 0, "xengnttab_unmap failed: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
int xen_be_copy_grant_refs(struct XenDevice *xendev,
|
||||
bool to_domain,
|
||||
XenGrantCopySegment segs[],
|
||||
unsigned int nr_segs)
|
||||
{
|
||||
xengnttab_grant_copy_segment_t *xengnttab_segs;
|
||||
unsigned int i;
|
||||
int rc;
|
||||
|
||||
assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
|
||||
|
||||
xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs);
|
||||
|
||||
for (i = 0; i < nr_segs; i++) {
|
||||
XenGrantCopySegment *seg = &segs[i];
|
||||
xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
|
||||
|
||||
if (to_domain) {
|
||||
xengnttab_seg->flags = GNTCOPY_dest_gref;
|
||||
xengnttab_seg->dest.foreign.domid = xen_domid;
|
||||
xengnttab_seg->dest.foreign.ref = seg->dest.foreign.ref;
|
||||
xengnttab_seg->dest.foreign.offset = seg->dest.foreign.offset;
|
||||
xengnttab_seg->source.virt = seg->source.virt;
|
||||
} else {
|
||||
xengnttab_seg->flags = GNTCOPY_source_gref;
|
||||
xengnttab_seg->source.foreign.domid = xen_domid;
|
||||
xengnttab_seg->source.foreign.ref = seg->source.foreign.ref;
|
||||
xengnttab_seg->source.foreign.offset =
|
||||
seg->source.foreign.offset;
|
||||
xengnttab_seg->dest.virt = seg->dest.virt;
|
||||
}
|
||||
|
||||
xengnttab_seg->len = seg->len;
|
||||
}
|
||||
|
||||
rc = xengnttab_grant_copy(xendev->gnttabdev, nr_segs, xengnttab_segs);
|
||||
|
||||
if (rc) {
|
||||
xen_pv_printf(xendev, 0, "xengnttab_copy failed: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_segs; i++) {
|
||||
xengnttab_grant_copy_segment_t *xengnttab_seg =
|
||||
&xengnttab_segs[i];
|
||||
|
||||
if (xengnttab_seg->status != GNTST_okay) {
|
||||
xen_pv_printf(xendev, 0, "segment[%u] status: %d\n", i,
|
||||
xengnttab_seg->status);
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
|
||||
g_free(xengnttab_segs);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* get xen backend device, allocate a new one if it doesn't exist.
|
||||
*/
|
||||
@ -149,18 +246,6 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
|
||||
}
|
||||
qemu_set_cloexec(xenevtchn_fd(xendev->evtchndev));
|
||||
|
||||
if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
|
||||
xendev->gnttabdev = xengnttab_open(NULL, 0);
|
||||
if (xendev->gnttabdev == NULL) {
|
||||
xen_pv_printf(NULL, 0, "can't open gnttab device\n");
|
||||
xenevtchn_close(xendev->evtchndev);
|
||||
qdev_unplug(DEVICE(xendev), NULL);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
xendev->gnttabdev = NULL;
|
||||
}
|
||||
|
||||
xen_pv_insert_xendev(xendev);
|
||||
|
||||
if (xendev->ops->alloc) {
|
||||
@ -322,6 +407,16 @@ static int xen_be_try_initialise(struct XenDevice *xendev)
|
||||
}
|
||||
}
|
||||
|
||||
if (xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
|
||||
xendev->gnttabdev = xengnttab_open(NULL, 0);
|
||||
if (xendev->gnttabdev == NULL) {
|
||||
xen_pv_printf(NULL, 0, "can't open gnttab device\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
xendev->gnttabdev = NULL;
|
||||
}
|
||||
|
||||
if (xendev->ops->initialise) {
|
||||
rc = xendev->ops->initialise(xendev);
|
||||
}
|
||||
@ -369,6 +464,10 @@ static void xen_be_disconnect(struct XenDevice *xendev, enum xenbus_state state)
|
||||
xendev->ops->disconnect) {
|
||||
xendev->ops->disconnect(xendev);
|
||||
}
|
||||
if (xendev->gnttabdev) {
|
||||
xengnttab_close(xendev->gnttabdev);
|
||||
xendev->gnttabdev = NULL;
|
||||
}
|
||||
if (xendev->be_state != state) {
|
||||
xen_be_set_state(xendev, state);
|
||||
}
|
||||
|
@ -42,6 +42,39 @@ void xen_be_register_common(void);
|
||||
int xen_be_register(const char *type, struct XenDevOps *ops);
|
||||
int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state);
|
||||
int xen_be_bind_evtchn(struct XenDevice *xendev);
|
||||
void xen_be_set_max_grant_refs(struct XenDevice *xendev,
|
||||
unsigned int nr_refs);
|
||||
void *xen_be_map_grant_refs(struct XenDevice *xendev, uint32_t *refs,
|
||||
unsigned int nr_refs, int prot);
|
||||
void xen_be_unmap_grant_refs(struct XenDevice *xendev, void *ptr,
|
||||
unsigned int nr_refs);
|
||||
|
||||
typedef struct XenGrantCopySegment {
|
||||
union {
|
||||
void *virt;
|
||||
struct {
|
||||
uint32_t ref;
|
||||
off_t offset;
|
||||
} foreign;
|
||||
} source, dest;
|
||||
size_t len;
|
||||
} XenGrantCopySegment;
|
||||
|
||||
int xen_be_copy_grant_refs(struct XenDevice *xendev,
|
||||
bool to_domain, XenGrantCopySegment segs[],
|
||||
unsigned int nr_segs);
|
||||
|
||||
static inline void *xen_be_map_grant_ref(struct XenDevice *xendev,
|
||||
uint32_t ref, int prot)
|
||||
{
|
||||
return xen_be_map_grant_refs(xendev, &ref, 1, prot);
|
||||
}
|
||||
|
||||
static inline void xen_be_unmap_grant_ref(struct XenDevice *xendev,
|
||||
void *ptr)
|
||||
{
|
||||
return xen_be_unmap_grant_refs(xendev, ptr, 1);
|
||||
}
|
||||
|
||||
/* actual backend drivers */
|
||||
extern struct XenDevOps xen_console_ops; /* xen_console.c */
|
||||
|
Loading…
Reference in New Issue
Block a user