|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v6 13/14] x86: add iommu_ops to modify and flush IOMMU mappings
>>> On 23.08.18 at 11:47, <paul.durrant@xxxxxxxxxx> wrote:
> --- a/xen/common/iommu_op.c
> +++ b/xen/common/iommu_op.c
> @@ -123,6 +123,156 @@ static int iommu_op_enable_modification(
> return 0;
> }
>
> +static int iommuop_map(struct xen_iommu_op_map *op)
> +{
> + struct domain *d, *currd = current->domain;
> + struct domain_iommu *iommu = dom_iommu(currd);
const (also in unmap)?
> +static int iommuop_unmap(struct xen_iommu_op_unmap *op)
> +{
> + struct domain *d, *currd = current->domain;
> + struct domain_iommu *iommu = dom_iommu(currd);
> + bfn_t bfn = _bfn(op->bfn);
> + mfn_t mfn;
> + bool readonly;
> + unsigned int prot;
> + struct page_info *page;
> + int rc;
> +
> + if ( op->pad ||
> + (op->flags & ~XEN_IOMMUOP_unmap_all) )
> + return -EINVAL;
> +
> + if ( !iommu->iommu_op_ranges )
> + return -EOPNOTSUPP;
> +
> + /* Per-device unmapping not yet supported */
> + if ( !(op->flags & XEN_IOMMUOP_unmap_all) )
> + return -EINVAL;
> +
> + if ( !rangeset_contains_singleton(iommu->iommu_op_ranges, bfn_x(bfn)) ||
Again the question about a malicious multi-vCPU guest trying to
utilize the gap between the check here and ...
> + iommu_lookup_page(currd, bfn, &mfn, &prot) ||
> + !mfn_valid(mfn) )
> + return -ENOENT;
> +
> + readonly = !(prot & IOMMUF_writable);
> +
> + d = rcu_lock_domain_by_any_id(op->domid);
> + if ( !d )
> + return -ESRCH;
> +
> + rc = get_paged_gfn(d, _gfn(op->gfn), !(prot & IOMMUF_writable), NULL,
> + &page);
> + if ( rc )
> + goto unlock;
> +
> + put_page(page); /* release extra reference just taken */
> +
> + rc = -EINVAL;
> + if ( !mfn_eq(page_to_mfn(page), mfn) )
> + goto unlock;
> +
> + /* release reference taken in map */
> + if ( !readonly )
> + put_page_type(page);
> + put_page(page);
> +
> + rc = rangeset_remove_singleton(iommu->iommu_op_ranges, bfn_x(bfn));
... the actual removal here.
> + if ( rc )
> + goto unlock;
You've already put the page ref - failure to remove needs to be fatal
to the guest, or you'd need to re-obtain refs.
> + if ( iommu_unmap_page(currd, bfn) )
> + rc = -EIO;
Similarly here: All records of the page having a mapping are gone.
> @@ -135,6 +285,22 @@ static void iommu_op(xen_iommu_op_t *op)
> op->status =
> iommu_op_enable_modification(&op->u.enable_modification);
> break;
>
> + case XEN_IOMMUOP_map:
> + this_cpu(iommu_dont_flush_iotlb) = 1;
> + op->status = iommuop_map(&op->u.map);
> + this_cpu(iommu_dont_flush_iotlb) = 0;
> + break;
> +
> + case XEN_IOMMUOP_unmap:
> + this_cpu(iommu_dont_flush_iotlb) = 1;
> + op->status = iommuop_unmap(&op->u.unmap);
> + this_cpu(iommu_dont_flush_iotlb) = 0;
> + break;
How is this flush suppression secure?
> --- a/xen/include/public/iommu_op.h
> +++ b/xen/include/public/iommu_op.h
> @@ -80,6 +80,113 @@ struct xen_iommu_op_enable_modification {
> #define XEN_IOMMU_CAP_per_device_mappings (1u <<
> _XEN_IOMMU_CAP_per_device_mappings)
> };
>
> +/*
> + * XEN_IOMMUOP_map: Map a guest page in the IOMMU.
> + */
Single line comment please (also below).
> +#define XEN_IOMMUOP_map 3
> +
> +struct xen_iommu_op_map {
> + /* IN - The domid of the guest */
> + domid_t domid;
> + /*
> + * IN - flags controlling the mapping. This should be a bitwise OR of the
> + * flags defined below.
> + */
> + uint16_t flags;
> +
> + /*
> + * Should the mapping be created for all initiators?
> + *
> + * NOTE: This flag is currently required as the implementation does not
> yet
> + * support pre-device mappings.
> + */
> +#define _XEN_IOMMUOP_map_all 0
> +#define XEN_IOMMUOP_map_all (1 << (_XEN_IOMMUOP_map_all))
Stray extra parentheses (also further down).
> +/*
> + * XEN_IOMMUOP_flush: Flush the IOMMU TLB.
> + */
> +#define XEN_IOMMUOP_flush 5
> +
> +struct xen_iommu_op_flush {
> + /*
> + * IN - flags controlling flushing. This should be a bitwise OR of the
> + * flags defined below.
> + */
> + uint16_t flags;
> +
> + /*
> + * Should the mappings flushed for all initiators?
> + *
> + * NOTE: This flag is currently required as the implementation does not
> yet
> + * support pre-device mappings.
> + */
> +#define _XEN_IOMMUOP_flush_all 0
> +#define XEN_IOMMUOP_flush_all (1 << (_XEN_IOMMUOP_flush_all))
> +
> + uint16_t pad0;
> + uint32_t pad1;
> + /*
> + * IN - Segment/Bus/Device/Function of the initiator.
> + *
> + * NOTE: This is ignored if XEN_IOMMUOP_flush_all is set.
> + */
> + uint64_t sbdf;
> +};
No means to flush a single mapping, or a sub-range of the entire
address space?
> --- a/xen/include/xlat.lst
> +++ b/xen/include/xlat.lst
> @@ -80,7 +80,10 @@
> ! iommu_op iommu_op.h
> ! iommu_op_buf iommu_op.h
> ! iommu_op_enable_modification iommu_op.h
> +! iommu_op_flush iommu_op.h
As long as there's no bfn_t in there, this could again be ? instead of ! ?
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |