[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v6 07/14] x86: add iommu_op to query reserved ranges
>>> On 23.08.18 at 11:47, <paul.durrant@xxxxxxxxxx> wrote: > This patch adds an iommu_op to allow the domain IOMMU reserved ranges to be > queried by the guest. > > NOTE: The number of reserved ranges is determined by system firmware, in > conjunction with Xen command line options, and is expected to be > small. Thus, to avoid over-complicating the code, there is no > pre-emption check within the operation. Hmm, RMRRs reportedly can cover a fair part of (the entire?) frame buffer of a graphics device. > @@ -100,16 +176,27 @@ long do_iommu_op(unsigned int nr_bufs, > return rc; > } > > +CHECK_iommu_reserved_range; > + > int compat_one_iommu_op(compat_iommu_op_buf_t *buf) > { > - compat_iommu_op_t cmp; > + compat_iommu_op_t cmp = {}; > + size_t offset; > + static const size_t op_size[] = { > + [XEN_IOMMUOP_query_reserved] = sizeof(struct > compat_iommu_op_query_reserved), > + }; > + size_t size; > xen_iommu_op_t nat; > + unsigned int u; > + int32_t status; > int rc; > > - if ( buf->size < sizeof(cmp) ) > + offset = offsetof(struct compat_iommu_op, u); > + > + if ( buf->size < offset ) > return -EFAULT; For some reason I notice this only now and here - -EFAULT isn't really appropriately describing the error condition here. -ENODATA or -ENOBUFS perhaps? > @@ -119,17 +206,82 @@ int compat_one_iommu_op(compat_iommu_op_buf_t *buf) > if ( rc ) > return rc; > > + if ( cmp.op >= ARRAY_SIZE(op_size) ) > + return -EOPNOTSUPP; > + > + size = op_size[array_index_nospec(cmp.op, ARRAY_SIZE(op_size))]; > + if ( buf->size < offset + size ) > + return -EFAULT; > + > + if ( copy_from_compat_offset((void *)&cmp.u, buf->h, offset, size) ) > + return -EFAULT; > + > + /* > + * The xlat magic doesn't quite know how to handle the union so > + * we need to fix things up here. > + */ > +#define XLAT_iommu_op_u_query_reserved XEN_IOMMUOP_query_reserved > + u = cmp.op; > + > +#define XLAT_iommu_op_query_reserved_HNDL_ranges(_d_, _s_) \ > + do \ > + { \ > + if ( !compat_handle_is_null((_s_)->ranges) ) \ > + { \ > + unsigned int *nr_entries = COMPAT_ARG_XLAT_VIRT_BASE; \ uint32_t (see below) or perhaps even better typeof(). > + xen_iommu_reserved_range_t *ranges = \ > + (void *)(nr_entries + 1); \ > + \ > + if ( sizeof(*nr_entries) + \ > + (sizeof(*ranges) * (_s_)->nr_entries) > \ > + COMPAT_ARG_XLAT_SIZE ) \ > + return -E2BIG; \ > + \ > + *nr_entries = (_s_)->nr_entries; \ > + set_xen_guest_handle((_d_)->ranges, ranges); \ > + } \ > + else \ > + set_xen_guest_handle((_d_)->ranges, NULL); \ > + } while (false) > + > XLAT_iommu_op(&nat, &cmp); > > +#undef XLAT_iommu_op_query_reserved_HNDL_ranges > + > iommu_op(&nat); > > + status = nat.status; > + > +#define XLAT_iommu_op_query_reserved_HNDL_ranges(_d_, _s_) \ > + do \ > + { \ > + if ( !compat_handle_is_null((_d_)->ranges) ) \ > + { \ > + unsigned int *nr_entries = COMPAT_ARG_XLAT_VIRT_BASE; \ > + compat_iommu_reserved_range_t *ranges = \ > + (void *)(nr_entries + 1); \ > + unsigned int nr = \ > + min_t(unsigned int, (_d_)->nr_entries, *nr_entries); \ > + \ > + if ( __copy_to_compat_offset((_d_)->ranges, 0, ranges, nr) ) \ > + status = -EFAULT; \ > + } \ > + } while (false) > + > XLAT_iommu_op(&cmp, &nat); > > + /* status will have been modified if __copy_to_compat_offset() failed */ > + cmp.status = status; > + > +#undef XLAT_iommu_op_query_reserved_HNDL_ranges > + > if ( __copy_field_to_compat(compat_handle_cast(buf->h, > compat_iommu_op_t), > &cmp, status) ) > return -EFAULT; > > +#undef XLAT_iommu_op_u_query_reserved > + > return 0; > } It's somehow more evident here, but I think even on the native path the nr_entries field doesn't get copied back despite it being an OUT. > --- a/xen/include/public/iommu_op.h > +++ b/xen/include/public/iommu_op.h > @@ -25,11 +25,50 @@ > > #include "xen.h" > > +typedef uint64_t xen_bfn_t; > + > +/* Structure describing a single range reserved in the IOMMU */ > +struct xen_iommu_reserved_range { > + xen_bfn_t start_bfn; > + unsigned int nr_frames; > + unsigned int pad; uint32_t > +}; > +typedef struct xen_iommu_reserved_range xen_iommu_reserved_range_t; > +DEFINE_XEN_GUEST_HANDLE(xen_iommu_reserved_range_t); > + > +/* > + * XEN_IOMMUOP_query_reserved: Query ranges reserved in the IOMMU. > + */ Single line comment please. > +#define XEN_IOMMUOP_query_reserved 1 > + > +struct xen_iommu_op_query_reserved { > + /* > + * IN/OUT - On entry this is the number of entries available > + * in the ranges array below. > + * On exit this is the actual number of reserved ranges. > + */ > + unsigned int nr_entries; > + unsigned int pad; uint32_t 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 |