[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v3 20/24] xen/passthrough: Extend XEN_DOMCTL_assign_device to support DT device
On Tue, 13 Jan 2015, Julien Grall wrote: > TODO: Update the commit message > > A device node is described by a path. It will be used to retrieved the > node in the device tree and assign the related device to the domain. > > Only device protected by an IOMMU can be assigned to a guest. > > Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx> > Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> > Cc: Wei Liu <wei.liu2@xxxxxxxxxx> > Cc: Jan Beulich <jbeulich@xxxxxxxx> > > --- > Changes in v2: > - Use a different number for XEN_DOMCTL_assign_dt_device > --- > tools/libxc/include/xenctrl.h | 10 ++++ > tools/libxc/xc_domain.c | 95 ++++++++++++++++++++++++++++++++-- > xen/drivers/passthrough/device_tree.c | 97 > +++++++++++++++++++++++++++++++++-- > xen/drivers/passthrough/iommu.c | 7 +++ > xen/drivers/passthrough/pci.c | 43 +++++++++++----- > xen/include/public/domctl.h | 15 +++++- > xen/include/xen/iommu.h | 3 ++ > 7 files changed, 249 insertions(+), 21 deletions(-) > > diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h > index d66571f..db45475 100644 > --- a/tools/libxc/include/xenctrl.h > +++ b/tools/libxc/include/xenctrl.h > @@ -2055,6 +2055,16 @@ int xc_deassign_device(xc_interface *xch, > uint32_t domid, > uint32_t machine_bdf); > > +int xc_assign_dt_device(xc_interface *xch, > + uint32_t domid, > + char *path); > +int xc_test_assign_dt_device(xc_interface *xch, > + uint32_t domid, > + char *path); > +int xc_deassign_dt_device(xc_interface *xch, > + uint32_t domid, > + char *path); > + > int xc_domain_memory_mapping(xc_interface *xch, > uint32_t domid, > unsigned long first_gfn, > diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c > index eb066cf..bca3aee 100644 > --- a/tools/libxc/xc_domain.c > +++ b/tools/libxc/xc_domain.c > @@ -1637,7 +1637,8 @@ int xc_assign_device( > > domctl.cmd = XEN_DOMCTL_assign_device; > domctl.domain = domid; > - domctl.u.assign_device.machine_sbdf = machine_sbdf; > + domctl.u.assign_device.dev = XEN_DOMCTL_DEV_PCI; > + domctl.u.assign_device.u.pci.machine_sbdf = machine_sbdf; > > return do_domctl(xch, &domctl); > } > @@ -1686,7 +1687,8 @@ int xc_test_assign_device( > > domctl.cmd = XEN_DOMCTL_test_assign_device; > domctl.domain = domid; > - domctl.u.assign_device.machine_sbdf = machine_sbdf; > + domctl.u.assign_device.dev = XEN_DOMCTL_DEV_PCI; > + domctl.u.assign_device.u.pci.machine_sbdf = machine_sbdf; > > return do_domctl(xch, &domctl); > } > @@ -1700,11 +1702,96 @@ int xc_deassign_device( > > domctl.cmd = XEN_DOMCTL_deassign_device; > domctl.domain = domid; > - domctl.u.assign_device.machine_sbdf = machine_sbdf; > - > + domctl.u.assign_device.dev = XEN_DOMCTL_DEV_PCI; > + domctl.u.assign_device.u.pci.machine_sbdf = machine_sbdf; > + > return do_domctl(xch, &domctl); > } > > +int xc_assign_dt_device( > + xc_interface *xch, > + uint32_t domid, > + char *path) > +{ > + int rc; > + size_t size = strlen(path); > + DECLARE_DOMCTL; > + DECLARE_HYPERCALL_BOUNCE(path, size, XC_HYPERCALL_BUFFER_BOUNCE_IN); > + > + if ( xc_hypercall_bounce_pre(xch, path) ) > + return -1; > + > + domctl.cmd = XEN_DOMCTL_assign_device; > + domctl.domain = (domid_t)domid; > + > + domctl.u.assign_device.dev = XEN_DOMCTL_DEV_DT; > + domctl.u.assign_device.u.dt.size = size; > + set_xen_guest_handle(domctl.u.assign_device.u.dt.path, path); > + > + rc = do_domctl(xch, &domctl); > + > + xc_hypercall_bounce_post(xch, path); > + > + return rc; > +} > + > +int xc_test_assign_dt_device( > + xc_interface *xch, > + uint32_t domid, > + char *path) > +{ > + int rc; > + size_t size = strlen(path); > + DECLARE_DOMCTL; > + DECLARE_HYPERCALL_BOUNCE(path, size, XC_HYPERCALL_BUFFER_BOUNCE_IN); > + > + if ( xc_hypercall_bounce_pre(xch, path) ) > + return -1; > + > + domctl.cmd = XEN_DOMCTL_test_assign_device; > + domctl.domain = (domid_t)domid; > + > + domctl.u.assign_device.dev = XEN_DOMCTL_DEV_DT; > + domctl.u.assign_device.u.dt.size = size; > + set_xen_guest_handle(domctl.u.assign_device.u.dt.path, path); > + > + rc = do_domctl(xch, &domctl); > + > + xc_hypercall_bounce_post(xch, path); > + > + return rc; > +} > + > +int xc_deassign_dt_device( > + xc_interface *xch, > + uint32_t domid, > + char *path) > +{ > + int rc; > + size_t size = strlen(path); > + DECLARE_DOMCTL; > + DECLARE_HYPERCALL_BOUNCE(path, size, XC_HYPERCALL_BUFFER_BOUNCE_IN); > + > + if ( xc_hypercall_bounce_pre(xch, path) ) > + return -1; > + > + domctl.cmd = XEN_DOMCTL_deassign_device; > + domctl.domain = (domid_t)domid; > + > + domctl.u.assign_device.dev = XEN_DOMCTL_DEV_DT; > + domctl.u.assign_device.u.dt.size = size; > + set_xen_guest_handle(domctl.u.assign_device.u.dt.path, path); > + > + rc = do_domctl(xch, &domctl); > + > + xc_hypercall_bounce_post(xch, path); > + > + return rc; > +} > + > + > + > + > int xc_domain_update_msi_irq( > xc_interface *xch, > uint32_t domid, > diff --git a/xen/drivers/passthrough/device_tree.c > b/xen/drivers/passthrough/device_tree.c > index d9b486e..11deb1d 100644 > --- a/xen/drivers/passthrough/device_tree.c > +++ b/xen/drivers/passthrough/device_tree.c > @@ -1,9 +1,6 @@ > /* > * Code to passthrough a device tree node to a guest > * > - * TODO: This contains only the necessary code to protected device passed to > - * dom0. It will need some updates when device passthrough will is added. > - * > * Julien Grall <julien.grall@xxxxxxxxxx> > * Copyright (c) 2014 Linaro Limited. > * > @@ -20,6 +17,7 @@ > > #include <xen/lib.h> > #include <xen/sched.h> > +#include <xen/guest_access.h> > #include <xen/iommu.h> > #include <xen/device_tree.h> > > @@ -85,6 +83,20 @@ fail: > return rc; > } > > +static bool_t iommu_dt_device_is_assigned(const struct dt_device_node *dev) > +{ > + bool_t assigned = 0; > + > + if ( !dt_device_is_protected(dev) ) > + return 1; Why return true here? > + spin_lock(&dtdevs_lock); > + assigned = !list_empty(&dev->domain_list); > + spin_unlock(&dtdevs_lock); > + > + return assigned; > +} > + > int iommu_dt_domain_init(struct domain *d) > { > struct hvm_iommu *hd = domain_hvm_iommu(d); > @@ -111,3 +123,82 @@ int iommu_release_dt_devices(struct domain *d) > > return 0; > } > + > +int iommu_do_dt_domctl(struct xen_domctl *domctl, struct domain *d, > + XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) > +{ > + int ret; > + struct dt_device_node *dev; > + > + /* TODO: How to deal with XSM? */ > + /* TODO: Do we need to check is_dying? Mostly to protect against > + * hypercall trying to passthrough a device while we are > + * dying. > + */ > + > + switch ( domctl->cmd ) > + { > + case XEN_DOMCTL_assign_device: > + ret = -ENOSYS; > + if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_DT ) > + break; > + > + ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path, > + domctl->u.assign_device.u.dt.size, > + &dev); > + if ( ret ) > + break; > + > + ret = iommu_assign_dt_device(d, dev); > + > + if ( ret ) > + printk(XENLOG_G_ERR "XEN_DOMCTL_assign_dt_device: assign \"%s\"" > + " to dom%u failed (%d)\n", > + dt_node_full_name(dev), d->domain_id, ret); > + break; > + > + case XEN_DOMCTL_deassign_device: > + ret = -ENOSYS; > + if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_DT ) > + break; > + > + ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path, > + domctl->u.assign_device.u.dt.size, > + &dev); > + if ( ret ) > + break; > + > + ret = iommu_deassign_dt_device(d, dev); > + > + if ( ret ) > + printk(XENLOG_G_ERR "XEN_DOMCTL_assign_dt_device: assign \"%s\"" > + " to dom%u failed (%d)\n", > + dt_node_full_name(dev), d->domain_id, ret); > + break; > + > + case XEN_DOMCTL_test_assign_device: > + ret = -ENOSYS; > + if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_DT ) > + break; > + > + ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path, > + domctl->u.assign_device.u.dt.size, > + &dev); > + if ( ret ) > + break; > + > + if ( iommu_dt_device_is_assigned(dev) ) > + { > + printk(XENLOG_G_ERR "%s already assigned, or not protected\n", > + dt_node_full_name(dev)); > + ret = -EINVAL; > + } > + break; > + > + default: > + ret = -ENOSYS; > + break; > + } > + > + return ret; > +} > diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c > index 8915244..02d5ec1 100644 > --- a/xen/drivers/passthrough/iommu.c > +++ b/xen/drivers/passthrough/iommu.c > @@ -337,6 +337,13 @@ int iommu_do_domctl( > ret = iommu_do_pci_domctl(domctl, d, u_domctl); > #endif > > + if ( ret != -ENOSYS ) > + return ret; > + > +#ifdef HAS_DEVICE_TREE > + ret = iommu_do_dt_domctl(domctl, d, u_domctl); > +#endif > + > return ret; > } > > diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c > index 9a47a37..ecc0cd1 100644 > --- a/xen/drivers/passthrough/pci.c > +++ b/xen/drivers/passthrough/pci.c > @@ -1497,6 +1497,7 @@ int iommu_do_pci_domctl( > u16 seg; > u8 bus, devfn; > int ret = 0; > + uint32_t machine_sbdf; > > switch ( domctl->cmd ) > { > @@ -1533,13 +1534,19 @@ int iommu_do_pci_domctl( > break; > > case XEN_DOMCTL_test_assign_device: > - ret = xsm_test_assign_device(XSM_HOOK, > domctl->u.assign_device.machine_sbdf); > + ret = -ENOSYS; > + if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_PCI ) > + break; > + > + machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf; > + > + ret = xsm_test_assign_device(XSM_HOOK, machine_sbdf); > if ( ret ) > break; > > - seg = domctl->u.assign_device.machine_sbdf >> 16; > - bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff; > - devfn = domctl->u.assign_device.machine_sbdf & 0xff; > + seg = machine_sbdf >> 16; > + bus = (machine_sbdf >> 8) & 0xff; > + devfn = machine_sbdf & 0xff; > > if ( device_assigned(seg, bus, devfn) ) > { > @@ -1551,19 +1558,25 @@ int iommu_do_pci_domctl( > break; > > case XEN_DOMCTL_assign_device: > + ret = -ENOSYS; > + if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_PCI ) > + break; > + > if ( unlikely(d->is_dying) ) > { > ret = -EINVAL; > break; > } > > - ret = xsm_assign_device(XSM_HOOK, d, > domctl->u.assign_device.machine_sbdf); > + machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf; > + > + ret = xsm_assign_device(XSM_HOOK, d, machine_sbdf); > if ( ret ) > break; > > - seg = domctl->u.assign_device.machine_sbdf >> 16; > - bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff; > - devfn = domctl->u.assign_device.machine_sbdf & 0xff; > + seg = machine_sbdf >> 16; > + bus = (machine_sbdf >> 8) & 0xff; > + devfn = machine_sbdf & 0xff; > > ret = device_assigned(seg, bus, devfn) ?: > assign_device(d, seg, bus, devfn); > @@ -1579,13 +1592,19 @@ int iommu_do_pci_domctl( > break; > > case XEN_DOMCTL_deassign_device: > - ret = xsm_deassign_device(XSM_HOOK, d, > domctl->u.assign_device.machine_sbdf); > + ret = -ENOSYS; > + if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_PCI ) > + break; > + > + machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf; > + > + ret = xsm_deassign_device(XSM_HOOK, d, machine_sbdf); > if ( ret ) > break; > > - seg = domctl->u.assign_device.machine_sbdf >> 16; > - bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff; > - devfn = domctl->u.assign_device.machine_sbdf & 0xff; > + seg = machine_sbdf >> 16; > + bus = (machine_sbdf >> 8) & 0xff; > + devfn = machine_sbdf & 0xff; > > spin_lock(&pcidevs_lock); > ret = deassign_device(d, seg, bus, devfn); > diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h > index b742b23..d905ab0 100644 > --- a/xen/include/public/domctl.h > +++ b/xen/include/public/domctl.h > @@ -475,12 +475,23 @@ typedef struct xen_domctl_sendtrigger > xen_domctl_sendtrigger_t; > DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendtrigger_t); > > > -/* Assign PCI device to HVM guest. Sets up IOMMU structures. */ > +/* Assign a device to a guest. Sets up IOMMU structures. */ > /* XEN_DOMCTL_assign_device */ > /* XEN_DOMCTL_test_assign_device */ > /* XEN_DOMCTL_deassign_device */ > +#define XEN_DOMCTL_DEV_PCI 0 > +#define XEN_DOMCTL_DEV_DT 1 > struct xen_domctl_assign_device { > - uint32_t machine_sbdf; /* machine PCI ID of assigned device */ > + uint32_t dev; /* XEN_DOMCTL_DEV_* */ > + union { > + struct { > + uint32_t machine_sbdf; /* machine PCI ID of assigned device */ > + } pci; > + struct { > + uint32_t size; /* Length of the path */ > + XEN_GUEST_HANDLE_64(char) path; /* path to the device tree node > */ > + } dt; > + } u; > }; > typedef struct xen_domctl_assign_device xen_domctl_assign_device_t; > DEFINE_XEN_GUEST_HANDLE(xen_domctl_assign_device_t); > diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h > index d03df14..d261277 100644 > --- a/xen/include/xen/iommu.h > +++ b/xen/include/xen/iommu.h > @@ -119,6 +119,9 @@ int iommu_deassign_dt_device(struct domain *d, struct > dt_device_node *dev); > int iommu_dt_domain_init(struct domain *d); > int iommu_release_dt_devices(struct domain *d); > > +int iommu_do_dt_domctl(struct xen_domctl *, struct domain *, > + XEN_GUEST_HANDLE_PARAM(xen_domctl_t)); > + > #endif /* HAS_DEVICE_TREE */ > > struct page_info; > -- > 2.1.4 > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |