Message ID | 1568388917-7287-7-git-send-email-olekstysh@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | iommu/arm: Add Renesas IPMMU-VMSA support + Linux's iommu_fwspec | expand |
On 13.09.2019 17:35, Oleksandr Tyshchenko wrote: > --- /dev/null > +++ b/xen/include/asm-arm/iommu_fwspec.h > @@ -0,0 +1,68 @@ > +/* > + * xen/include/asm-arm/iommu_fwspec.h > + * > + * Contains a common structure to hold the per-device firmware data and > + * declaration of functions used to maintain that data > + * > + * Based on Linux's iommu_fwspec support you can find at: > + * include/linux/iommu.h > + * > + * Copyright (C) 2007-2008 Advanced Micro Devices, Inc. > + * > + * Copyright (C) 2019 EPAM Systems Inc. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms and conditions of the GNU General Public > + * License, version 2, as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * General Public License for more details. > + * > + * You should have received a copy of the GNU General Public > + * License along with this program; If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#ifndef __ARCH_ARM_IOMMU_FWSPEC_H__ > +#define __ARCH_ARM_IOMMU_FWSPEC_H__ > + > +/* per-device IOMMU instance data */ > +struct iommu_fwspec { > + /* this device's IOMMU */ > + struct device *iommu_dev; > + /* IOMMU driver private data for this device */ > + void *iommu_priv; > + /* number of associated device IDs */ > + unsigned int num_ids; > + /* IDs which this device may present to the IOMMU */ > + uint32_t ids[1]; > +}; Note that you abuse xrealloc_flex_struct() when using it with such a type: The last field is _not_ a flexible array member. Compilers might legitimately warn if they can prove that you access p->ids[1] anywhere, despite you (presumably) having allocated enough space. (I haven't been able to think of a way for the macro to actually detect and hence refuse such wrong uses.) Jan
On 16.09.19 13:40, Jan Beulich wrote: Hi, Jan > >> + >> +/* per-device IOMMU instance data */ >> +struct iommu_fwspec { >> + /* this device's IOMMU */ >> + struct device *iommu_dev; >> + /* IOMMU driver private data for this device */ >> + void *iommu_priv; >> + /* number of associated device IDs */ >> + unsigned int num_ids; >> + /* IDs which this device may present to the IOMMU */ >> + uint32_t ids[1]; >> +}; > Note that you abuse xrealloc_flex_struct() when using it with such > a type: The last field is _not_ a flexible array member. Compilers > might legitimately warn if they can prove that you access > p->ids[1] anywhere, despite you (presumably) having allocated enough > space. (I haven't been able to think of a way for the macro to > actually detect and hence refuse such wrong uses.) Indeed, you are right. I am in doubt, whether to retain ported from Linux code (ids[1]) and mention about such abuse or change it to deal with real flexible array member (ids[]). Any thoughts?
On 16.09.2019 20:08, Oleksandr wrote: > On 16.09.19 13:40, Jan Beulich wrote: >>> +/* per-device IOMMU instance data */ >>> +struct iommu_fwspec { >>> + /* this device's IOMMU */ >>> + struct device *iommu_dev; >>> + /* IOMMU driver private data for this device */ >>> + void *iommu_priv; >>> + /* number of associated device IDs */ >>> + unsigned int num_ids; >>> + /* IDs which this device may present to the IOMMU */ >>> + uint32_t ids[1]; >>> +}; >> Note that you abuse xrealloc_flex_struct() when using it with such >> a type: The last field is _not_ a flexible array member. Compilers >> might legitimately warn if they can prove that you access >> p->ids[1] anywhere, despite you (presumably) having allocated enough >> space. (I haven't been able to think of a way for the macro to >> actually detect and hence refuse such wrong uses.) > > Indeed, you are right. I am in doubt, whether to retain ported from > Linux code (ids[1]) > > and mention about such abuse or change it to deal with real flexible > array member (ids[]). Any thoughts? I'm of the strong opinion that you should switch to [] (or at least [0]) notation. Jan
On 17.09.19 09:12, Jan Beulich wrote: Hi, Jan > On 16.09.2019 20:08, Oleksandr wrote: >> On 16.09.19 13:40, Jan Beulich wrote: >>>> +/* per-device IOMMU instance data */ >>>> +struct iommu_fwspec { >>>> + /* this device's IOMMU */ >>>> + struct device *iommu_dev; >>>> + /* IOMMU driver private data for this device */ >>>> + void *iommu_priv; >>>> + /* number of associated device IDs */ >>>> + unsigned int num_ids; >>>> + /* IDs which this device may present to the IOMMU */ >>>> + uint32_t ids[1]; >>>> +}; >>> Note that you abuse xrealloc_flex_struct() when using it with such >>> a type: The last field is _not_ a flexible array member. Compilers >>> might legitimately warn if they can prove that you access >>> p->ids[1] anywhere, despite you (presumably) having allocated enough >>> space. (I haven't been able to think of a way for the macro to >>> actually detect and hence refuse such wrong uses.) >> Indeed, you are right. I am in doubt, whether to retain ported from >> Linux code (ids[1]) >> >> and mention about such abuse or change it to deal with real flexible >> array member (ids[]). Any thoughts? > I'm of the strong opinion that you should switch to [] (or at > least [0]) notation. I got it. Well, will switch to ids[] if there are no objections. Thank you.
Hi, On 17/09/2019 19:18, Oleksandr wrote: > > On 17.09.19 09:12, Jan Beulich wrote: > > Hi, Jan > >> On 16.09.2019 20:08, Oleksandr wrote: >>> On 16.09.19 13:40, Jan Beulich wrote: >>>>> +/* per-device IOMMU instance data */ >>>>> +struct iommu_fwspec { >>>>> + /* this device's IOMMU */ >>>>> + struct device *iommu_dev; >>>>> + /* IOMMU driver private data for this device */ >>>>> + void *iommu_priv; >>>>> + /* number of associated device IDs */ >>>>> + unsigned int num_ids; >>>>> + /* IDs which this device may present to the IOMMU */ >>>>> + uint32_t ids[1]; >>>>> +}; >>>> Note that you abuse xrealloc_flex_struct() when using it with such >>>> a type: The last field is _not_ a flexible array member. Compilers >>>> might legitimately warn if they can prove that you access >>>> p->ids[1] anywhere, despite you (presumably) having allocated enough >>>> space. (I haven't been able to think of a way for the macro to >>>> actually detect and hence refuse such wrong uses.) >>> Indeed, you are right. I am in doubt, whether to retain ported from >>> Linux code (ids[1]) >>> >>> and mention about such abuse or change it to deal with real flexible >>> array member (ids[]). Any thoughts? >> I'm of the strong opinion that you should switch to [] (or at >> least [0]) notation. > > I got it. Well, will switch to ids[] if there are no objections. I suspect the rationale to use 1 rather than 0 is to avoid the re-allocation in the common case where a device has a single ID. I would like to retain the similar behavior. The ids[1] is probably the most pretty way to do it. Another solution would to use xmalloc_bytes() for the initial allocation of xmalloc_bytes(). Cheers,
On 19.09.2019 12:12, Julien Grall wrote: > Hi, > > On 17/09/2019 19:18, Oleksandr wrote: >> >> On 17.09.19 09:12, Jan Beulich wrote: >> >> Hi, Jan >> >>> On 16.09.2019 20:08, Oleksandr wrote: >>>> On 16.09.19 13:40, Jan Beulich wrote: >>>>>> +/* per-device IOMMU instance data */ >>>>>> +struct iommu_fwspec { >>>>>> + /* this device's IOMMU */ >>>>>> + struct device *iommu_dev; >>>>>> + /* IOMMU driver private data for this device */ >>>>>> + void *iommu_priv; >>>>>> + /* number of associated device IDs */ >>>>>> + unsigned int num_ids; >>>>>> + /* IDs which this device may present to the IOMMU */ >>>>>> + uint32_t ids[1]; >>>>>> +}; >>>>> Note that you abuse xrealloc_flex_struct() when using it with such >>>>> a type: The last field is _not_ a flexible array member. Compilers >>>>> might legitimately warn if they can prove that you access >>>>> p->ids[1] anywhere, despite you (presumably) having allocated enough >>>>> space. (I haven't been able to think of a way for the macro to >>>>> actually detect and hence refuse such wrong uses.) >>>> Indeed, you are right. I am in doubt, whether to retain ported from >>>> Linux code (ids[1]) >>>> >>>> and mention about such abuse or change it to deal with real flexible >>>> array member (ids[]). Any thoughts? >>> I'm of the strong opinion that you should switch to [] (or at >>> least [0]) notation. >> >> I got it. Well, will switch to ids[] if there are no objections. > > I suspect the rationale to use 1 rather than 0 is to avoid the re-allocation in > the common case where a device has a single ID. > > I would like to retain the similar behavior. The ids[1] is probably the most > pretty way to do it. > > Another solution would to use xmalloc_bytes() for the initial allocation of > xmalloc_bytes(). Why not use xmalloc_flex_<whatever>() on the first allocation, too? Jan
Hi, all. >>>>>>> +struct iommu_fwspec { >>>>>>> + /* this device's IOMMU */ >>>>>>> + struct device *iommu_dev; >>>>>>> + /* IOMMU driver private data for this device */ >>>>>>> + void *iommu_priv; >>>>>>> + /* number of associated device IDs */ >>>>>>> + unsigned int num_ids; >>>>>>> + /* IDs which this device may present to the IOMMU */ >>>>>>> + uint32_t ids[1]; >>>>>>> +}; >>>>>> Note that you abuse xrealloc_flex_struct() when using it with such >>>>>> a type: The last field is _not_ a flexible array member. Compilers >>>>>> might legitimately warn if they can prove that you access >>>>>> p->ids[1] anywhere, despite you (presumably) having allocated enough >>>>>> space. (I haven't been able to think of a way for the macro to >>>>>> actually detect and hence refuse such wrong uses.) >>>>> Indeed, you are right. I am in doubt, whether to retain ported from >>>>> Linux code (ids[1]) >>>>> >>>>> and mention about such abuse or change it to deal with real flexible >>>>> array member (ids[]). Any thoughts? >>>> I'm of the strong opinion that you should switch to [] (or at >>>> least [0]) notation. >>> I got it. Well, will switch to ids[] if there are no objections. >> I suspect the rationale to use 1 rather than 0 is to avoid the re-allocation in >> the common case where a device has a single ID. >> >> I would like to retain the similar behavior. The ids[1] is probably the most >> pretty way to do it. >> >> Another solution would to use xmalloc_bytes() for the initial allocation of >> xmalloc_bytes(). > Why not use xmalloc_flex_<whatever>() on the first allocation, too? Hmm, why not? Looks like the xmalloc_flex_struct fits here. The first allocation would be: fwspec = xmalloc_flex_struct(struct iommu_fwspec, ids, 1); The re-allocation for the devices with single ID would do effectively nothing (assuming that _xrealloc will recognize that size is the same): fwspec = xrealloc_flex_struct(fwspec, ids, fwspec->num_ids + num_ids); Julien, what do you think?
On 19/09/2019 11:57, Oleksandr wrote: > > Hi, all. Hi, > > >>>>>>>> +struct iommu_fwspec { >>>>>>>> + /* this device's IOMMU */ >>>>>>>> + struct device *iommu_dev; >>>>>>>> + /* IOMMU driver private data for this device */ >>>>>>>> + void *iommu_priv; >>>>>>>> + /* number of associated device IDs */ >>>>>>>> + unsigned int num_ids; >>>>>>>> + /* IDs which this device may present to the IOMMU */ >>>>>>>> + uint32_t ids[1]; >>>>>>>> +}; >>>>>>> Note that you abuse xrealloc_flex_struct() when using it with such >>>>>>> a type: The last field is _not_ a flexible array member. Compilers >>>>>>> might legitimately warn if they can prove that you access >>>>>>> p->ids[1] anywhere, despite you (presumably) having allocated enough >>>>>>> space. (I haven't been able to think of a way for the macro to >>>>>>> actually detect and hence refuse such wrong uses.) >>>>>> Indeed, you are right. I am in doubt, whether to retain ported from >>>>>> Linux code (ids[1]) >>>>>> >>>>>> and mention about such abuse or change it to deal with real flexible >>>>>> array member (ids[]). Any thoughts? >>>>> I'm of the strong opinion that you should switch to [] (or at >>>>> least [0]) notation. >>>> I got it. Well, will switch to ids[] if there are no objections. >>> I suspect the rationale to use 1 rather than 0 is to avoid the re-allocation in >>> the common case where a device has a single ID. >>> >>> I would like to retain the similar behavior. The ids[1] is probably the most >>> pretty way to do it. >>> >>> Another solution would to use xmalloc_bytes() for the initial allocation of >>> xmalloc_bytes(). >> Why not use xmalloc_flex_<whatever>() on the first allocation, too? > Hmm, why not? Looks like the xmalloc_flex_struct fits here. > > The first allocation would be: > > fwspec = xmalloc_flex_struct(struct iommu_fwspec, ids, 1); > > > The re-allocation for the devices with single ID would do effectively nothing > (assuming that _xrealloc will recognize that size is the same): > > fwspec = xrealloc_flex_struct(fwspec, ids, fwspec->num_ids + num_ids); > > > Julien, what do you think? I am happy with that. The first allocation would need a comment on top explaining the reason of the "1". Cheers,
Hi, all. >> >>>>>>>>> +struct iommu_fwspec { >>>>>>>>> + /* this device's IOMMU */ >>>>>>>>> + struct device *iommu_dev; >>>>>>>>> + /* IOMMU driver private data for this device */ >>>>>>>>> + void *iommu_priv; >>>>>>>>> + /* number of associated device IDs */ >>>>>>>>> + unsigned int num_ids; >>>>>>>>> + /* IDs which this device may present to the IOMMU */ >>>>>>>>> + uint32_t ids[1]; >>>>>>>>> +}; >>>>>>>> Note that you abuse xrealloc_flex_struct() when using it with such >>>>>>>> a type: The last field is _not_ a flexible array member. Compilers >>>>>>>> might legitimately warn if they can prove that you access >>>>>>>> p->ids[1] anywhere, despite you (presumably) having allocated >>>>>>>> enough >>>>>>>> space. (I haven't been able to think of a way for the macro to >>>>>>>> actually detect and hence refuse such wrong uses.) >>>>>>> Indeed, you are right. I am in doubt, whether to retain ported from >>>>>>> Linux code (ids[1]) >>>>>>> >>>>>>> and mention about such abuse or change it to deal with real >>>>>>> flexible >>>>>>> array member (ids[]). Any thoughts? >>>>>> I'm of the strong opinion that you should switch to [] (or at >>>>>> least [0]) notation. >>>>> I got it. Well, will switch to ids[] if there are no objections. >>>> I suspect the rationale to use 1 rather than 0 is to avoid the >>>> re-allocation in >>>> the common case where a device has a single ID. >>>> >>>> I would like to retain the similar behavior. The ids[1] is probably >>>> the most >>>> pretty way to do it. >>>> >>>> Another solution would to use xmalloc_bytes() for the initial >>>> allocation of >>>> xmalloc_bytes(). >>> Why not use xmalloc_flex_<whatever>() on the first allocation, too? >> Hmm, why not? Looks like the xmalloc_flex_struct fits here. >> >> The first allocation would be: >> >> fwspec = xmalloc_flex_struct(struct iommu_fwspec, ids, 1); >> >> >> The re-allocation for the devices with single ID would do effectively >> nothing (assuming that _xrealloc will recognize that size is the same): >> >> fwspec = xrealloc_flex_struct(fwspec, ids, fwspec->num_ids + num_ids); >> >> >> Julien, what do you think? > > I am happy with that. The first allocation would need a comment on top > explaining the reason of the "1". Sure, will add.
diff --git a/xen/drivers/passthrough/arm/Makefile b/xen/drivers/passthrough/arm/Makefile index 4abb87a..5fbad45 100644 --- a/xen/drivers/passthrough/arm/Makefile +++ b/xen/drivers/passthrough/arm/Makefile @@ -1,2 +1,2 @@ -obj-y += iommu.o iommu_helpers.o +obj-y += iommu.o iommu_helpers.o iommu_fwspec.o obj-$(CONFIG_ARM_SMMU) += smmu.o diff --git a/xen/drivers/passthrough/arm/iommu_fwspec.c b/xen/drivers/passthrough/arm/iommu_fwspec.c new file mode 100644 index 0000000..7046faf --- /dev/null +++ b/xen/drivers/passthrough/arm/iommu_fwspec.c @@ -0,0 +1,93 @@ +/* + * xen/drivers/passthrough/arm/iommu_fwspec.c + * + * Contains functions to maintain per-device firmware data + * + * Based on Linux's iommu_fwspec support you can find at: + * drivers/iommu/iommu.c + * + * Copyright (C) 2007-2008 Advanced Micro Devices, Inc. + * + * Copyright (C) 2019 EPAM Systems Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms and conditions of the GNU General Public + * License, version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; If not, see <http://www.gnu.org/licenses/>. + */ + +#include <xen/iommu.h> +#include <xen/lib.h> + +#include <asm/device.h> +#include <asm/iommu_fwspec.h> + +int iommu_fwspec_init(struct device *dev, struct device *iommu_dev) +{ + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + + if ( fwspec ) + { + /* We expect the device to be protected by only one IOMMU. */ + if ( fwspec->iommu_dev != iommu_dev ) + return -EINVAL; + + return 0; + } + + fwspec = xzalloc(struct iommu_fwspec); + if ( !fwspec ) + return -ENOMEM; + + fwspec->iommu_dev = iommu_dev; + dev_iommu_fwspec_set(dev, fwspec); + + return 0; +} + +void iommu_fwspec_free(struct device *dev) +{ + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + + xfree(fwspec); + dev_iommu_fwspec_set(dev, NULL); +} + +int iommu_fwspec_add_ids(struct device *dev, uint32_t *ids, + unsigned int num_ids) +{ + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + unsigned int i; + + if ( !fwspec ) + return -EINVAL; + + fwspec = xrealloc_flex_struct(fwspec, ids, fwspec->num_ids + num_ids); + if ( !fwspec ) + return -ENOMEM; + + dev_iommu_fwspec_set(dev, fwspec); + + for ( i = 0; i < num_ids; i++ ) + fwspec->ids[fwspec->num_ids + i] = ids[i]; + + fwspec->num_ids += num_ids; + + return 0; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/asm-arm/device.h b/xen/include/asm-arm/device.h index ee1c3bc..ee7cff2 100644 --- a/xen/include/asm-arm/device.h +++ b/xen/include/asm-arm/device.h @@ -18,6 +18,7 @@ struct device struct dt_device_node *of_node; /* Used by drivers imported from Linux */ #endif struct dev_archdata archdata; + struct iommu_fwspec *iommu_fwspec; /* per-device IOMMU instance data */ }; typedef struct device device_t; diff --git a/xen/include/asm-arm/iommu_fwspec.h b/xen/include/asm-arm/iommu_fwspec.h new file mode 100644 index 0000000..8ce4da1 --- /dev/null +++ b/xen/include/asm-arm/iommu_fwspec.h @@ -0,0 +1,68 @@ +/* + * xen/include/asm-arm/iommu_fwspec.h + * + * Contains a common structure to hold the per-device firmware data and + * declaration of functions used to maintain that data + * + * Based on Linux's iommu_fwspec support you can find at: + * include/linux/iommu.h + * + * Copyright (C) 2007-2008 Advanced Micro Devices, Inc. + * + * Copyright (C) 2019 EPAM Systems Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms and conditions of the GNU General Public + * License, version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __ARCH_ARM_IOMMU_FWSPEC_H__ +#define __ARCH_ARM_IOMMU_FWSPEC_H__ + +/* per-device IOMMU instance data */ +struct iommu_fwspec { + /* this device's IOMMU */ + struct device *iommu_dev; + /* IOMMU driver private data for this device */ + void *iommu_priv; + /* number of associated device IDs */ + unsigned int num_ids; + /* IDs which this device may present to the IOMMU */ + uint32_t ids[1]; +}; + +int iommu_fwspec_init(struct device *dev, struct device *iommu_dev); +void iommu_fwspec_free(struct device *dev); +int iommu_fwspec_add_ids(struct device *dev, uint32_t *ids, + unsigned int num_ids); + +static inline struct iommu_fwspec *dev_iommu_fwspec_get(struct device *dev) +{ + return dev->iommu_fwspec; +} + +static inline void dev_iommu_fwspec_set(struct device *dev, + struct iommu_fwspec *fwspec) +{ + dev->iommu_fwspec = fwspec; +} + +#endif /* __ARCH_ARM_IOMMU_FWSPEC_H__ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */