From: Eric Auger <eric.auger@redhat.com> Date: 2016-08-02 17:24:13
This series implements the MSI address mapping/unmapping in the MSI layer.
IOMMU binding happens on pci_enable_msi since this function can sleep and
return errors. On msi_domain_set_affinity, msi_domain_(de)activate, which
are not allowed to sleep, we simply look for the already existing binding.
Irqchips likely to be downstream to iommus (not bypassing MSIs) are supposed
to register their MSI doorbells. This make possible to retrieve their
characteristics, detect whether MSI assignment is safe and report to the
userspace the size/alignment of the guest PA window to provision for MSI
mapping.
A new MSI domain info flag value is introduced to report whether the msi
domain implements IRQ remapping. GIC v3 ITS is the first MSI controller
advertising it. This flag value will be used by VFIO subsystem to
determine whether MSI forwarding is safe.
More details & context can be found at:
http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/
Best Regards
Eric
Git: complete series available at
https://github.com/eauger/linux/tree/v4.7-rc7-passthrough-v12
History:
v11 -> v12
- rework kernel-docs, misc renamings and style issue fixing
- remove WARN_ON in msi_compose around iommu_msi_msg_pa_to_va,
instead return the error
- new code structure in "genirq/msi: Map/unmap the MSI doorbells on
msi_domain_alloc/free_irqs"
- introduce new msi_desc flags and let free_msi_irqs do the deallocation
- irq_get_msi_doorbell_info returns NULL in case of error
- clarify case where MSI controller stands inbetween the device and the
IOMMU
v10 -> v11:
- restored irq_chip msi_doorbell_info since lookup function introduced
in v10 (taking the chip_data as parameter) did not work for ITS and
most probably for other irqchips/
- changed the registration API
- eventually tested with GICv3 ITS
v9 -> v10:
- was forced to introduce important changes on parts that were reviewed
already :-( I took the initiative to replace the irqchip's
get_doorbell_info callback by a new API, msi-doorbell).
the new API makes possible to register, lookup doorbells and also compute
the total requirements and IRQ safety flag used by VFIO.
- also added code in GICv3 ITS to register a global doorbell.
v8 -> v9:
- use a union in irq_chip_msi_doorbell_info + boolean telling whether the
doorbell is percpu
- decouple irq_data parsing from the actual mapping/unmapping in
msi_handle_doorbell_mappings
- fix misc style issues
v7 -> v8:
take into account Marc's comments:
- use iommu_msi_msg_pa_to_va with new proto
- change in irq_chip_msi_doorbell_info struct definition:
prot and size became shared between all doorbells and phys_addr_t __percpu
- cleanups in v2m irqchip
- eventually did not touch MSI_FLAG_IRQ_REMAPPING naming
- On msi_handle_doorbell_mappings, stop on the first irqchip where doorbells
can be found
- fix resource deallocation on mapping failure in msi_domain_alloc_irqs
v6 -> v7:
- do alloc/map handling on pci_enable_msi and search on msi_(de)domain_activate
- add msi_doorbell_info callback in irq-chip to retrieve the characteristics
of doorbells
RFC v5 -> patch v6:
- split to ease the review process
- rebase on default iommu domain code (irq_data_to_msi_mapping_domain
checks IOMMU_DOMAIN_DMA type)
- fix unmap sequence on msi_domain_set_affinity (reported by Marc):
unmap the previous doorbell when the new one has been mapped & written to
the device, ie. irq_chip_write_msi_msg.
- "msi: msi_compose wrapper removed" following change above
- add size parameter to iommu_get_reserved_iova API following Marc's request
RFC v4 -> RFC v5:
- take into account Thomas' comments on MSI related patches
- split "msi: IOMMU map the doorbell address when needed"
- increase readability and add comments
- fix style issues
- split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
- platform ITS now advertises IOMMU_CAP_INTR_REMAP
- fix compilation issue with CONFIG_IOMMU API unset
- arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING
RFC v3 -> v4:
- Move doorbell mapping/unmapping in msi.c
- fix ref count issue on set_affinity: in case of a change in the address
the previous address is decremented
- doorbell map/unmap now is done on msi composition. Should allow the use
case for platform MSI controllers
- create dma-reserved-iommu.h/c exposing/implementing a new API dedicated
to reserved IOVA management (looking like dma-iommu glue)
- series reordering to ease the review:
- first part is related to IOMMU
- second related to MSI sub-system
- third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal)
- expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO
[this partially addresses Marc's comments on iommu_get/put_single_reserved
size/alignment problematic - which I did not ignore - but I don't know
how much I can do at the moment]
RFC v2 -> RFC v3:
- should fix wrong handling of some CONFIG combinations:
CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
- fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)
PATCH v1 -> RFC v2:
- reverted to RFC since it looks more reasonable ;-) the code is split
between VFIO, IOMMU, MSI controller and I am not sure I did the right
choices. Also API need to be further discussed.
- iova API usage in arm-smmu.c.
- MSI controller natively programs the MSI addr with either the PA or IOVA.
This is not done anymore in vfio-pci driver as suggested by Alex.
- check irq remapping capability of the group
RFC v1 [2] -> PATCH v1:
- use the existing dma map/unmap ioctl interface with a flag to register a
reserved IOVA range. Use the legacy Rb to store this special vfio_dma.
- a single reserved IOVA contiguous region now is allowed
- use of an RB tree indexed by PA to store allocated reserved slots
- use of a vfio_domain iova_domain to manage iova allocation within the
window provided by the userspace
- vfio alloc_map/unmap_free take a vfio_group handle
- vfio_group handle is cached in vfio_pci_device
- add ref counting to bindings
- user modality enabled at the end of the series
Eric Auger (11):
genirq/msi: export msi_get_domain_info
genirq/msi: msi_compose wrapper
genirq: Introduce irq_get_msi_doorbell_info
genirq/msi: Allow MSI doorbell (un)registration
genirq/msi: msi_doorbell_calc_pages
genirq/msi: msi_doorbell_safe
irqchip/gic-v2m: Register the MSI global doorbell
irqchip/gicv3-its: Register the MSI global doorbell
genirq/msi: Introduce msi_desc flags
genirq/msi: Map/unmap the MSI doorbells on msi_domain_alloc/free_irqs
genirq/msi: Use the MSI doorbell's IOVA when requested
drivers/iommu/Kconfig | 1 +
drivers/irqchip/irq-gic-v2m.c | 35 ++++++--
drivers/irqchip/irq-gic-v3-its.c | 67 ++++++++++----
drivers/pci/msi.c | 2 +-
include/linux/irq.h | 23 ++++-
include/linux/msi-doorbell.h | 82 +++++++++++++++++
include/linux/msi.h | 14 +++
kernel/irq/Kconfig | 4 +
kernel/irq/Makefile | 1 +
kernel/irq/msi-doorbell.c | 138 +++++++++++++++++++++++++++++
kernel/irq/msi.c | 187 +++++++++++++++++++++++++++++++++++++--
11 files changed, 517 insertions(+), 37 deletions(-)
create mode 100644 include/linux/msi-doorbell.h
create mode 100644 kernel/irq/msi-doorbell.c
--
1.9.1
From: Eric Auger <eric.auger@redhat.com> Date: 2016-08-02 17:24:28
We plan to use msi_get_domain_info in VFIO module so let's export it.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v2 -> v3:
- remove static implementation in case CONFIG_PCI_MSI_IRQ_DOMAIN is not set
---
kernel/irq/msi.c | 1 +
1 file changed, 1 insertion(+)
From: Eric Auger <eric.auger@redhat.com> Date: 2016-08-02 17:25:51
This patch adds the registration of the MSI global doorbell in
gicv3-its driver plus the implementation for irq_chip
irq_get_msi_doorbell_info ops.
This will allow the msi layer to iommu_map this doorbell when
requested.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v11 -> v12:
- use new irq_get_msi_doorbell_info name
- simplify error handling
v10 -> v11:
- adapt to new doorbell registration API and implement msi_doorbell_info
---
drivers/irqchip/irq-gic-v3-its.c | 67 ++++++++++++++++++++++++++++------------
1 file changed, 48 insertions(+), 19 deletions(-)
From: Eric Auger <eric.auger@redhat.com> Date: 2016-08-02 17:26:06
This patch handles the iommu mapping of MSI doorbells that require to
be mapped in an iommu domain. This happens on msi_domain_alloc/free_irqs
since this is called in code that can sleep (pci_enable/disable_msi):
iommu_map/unmap is not stated as atomic. On msi_domain_(de)activate and
msi_domain_set_affinity, which must be atomic, we just lookup for this
pre-allocated/mapped IOVA.
If we detect the device sending MSIs is in front of an IOMMU that do not
bypass MSIs but we can't find any doorbell to map we fail. This means we
currently do not support MSI controllers inbetween the device and the
IOMMU. In the future, those controllers, typically integrated into the
PCI host controller may also register a doorbell declared as not mappable.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v11 -> v12:
- introduce intermediate helpers:
msi_get_doorbell_info, msi_map_global_doorbell, msi_map_percpu_doorbell
- add kernel-doc comments
- remove desc->irq reset and cleanup in case of failure and set
MSI_DESC_FLAG_FUNCTION instead
- add comments
v10 -> v11:
- restore v9 version based on irq_chip msi_doorbell_info
v9 -> v10:
- use irqchip API to lookup for the chip_data's doorbell
v8 -> v9:
- decouple irq_data parsing from the actual mapping/unmapping
v7 -> v8:
- new percpu pointer type
- exit from the irq domain hierarchy parsing on first map/unmap success
- reset desc->irq to 0 on mapping failure
v7: creation
---
kernel/irq/msi.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 148 insertions(+), 6 deletions(-)
@@ -14,6 +14,9 @@#include<linux/irq.h>#include<linux/irqdomain.h>#include<linux/msi.h>+#include<linux/msi-iommu.h>+#include<linux/iommu.h>+#include<linux/msi-doorbell.h>/* Temparory solution for building, will be removed later */#include<linux/pci.h>
@@ -322,6 +325,131 @@ int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,}/**+*msi_get_doorbell_info-returntheMSIdoorbelldescriptorcorresponding+*toanirqdata+*@data:irqdatahandle+*+*Return:thedoorbelldescriptorpointerifany,NULLifnone,anERR_PTR+*otherwise+*/+staticstructmsi_doorbell_info*msi_get_doorbell_info(structirq_data*data)+{+structirq_chip*chip;++while(data){+chip=irq_data_get_irq_chip(data);+if(chip->irq_get_msi_doorbell_info)+break;+data=data->parent_data;+}++if(!data)+returnNULL;++returnchip->irq_get_msi_doorbell_info(data);+}++/**+*msi_map_global_doorbell-iommumap/unmaptheglobaldoorbellphysical+*address+*@domain:iommudomainthemappingisassociatedto+*@dbi:doorbelldescriptor+*@map:trueifmapoperation,falseifunmapoperation+*+*Return:0onsuccessoranerrorcode+*/+staticintmsi_map_global_doorbell(structiommu_domain*domain,+conststructmsi_doorbell_info*dbi,boolmap)+{+dma_addr_tiova;+intret=0;++if(map)+ret=iommu_msi_get_doorbell_iova(domain,dbi->global_doorbell,+dbi->size,dbi->prot,&iova);+else+iommu_msi_put_doorbell_iova(domain,dbi->global_doorbell);+returnret;+}++/**+*msi_map_percpu_doorbell-iommumap/unmapthepercpudoorbellphysical+*addresses+*@domain:iommudomainthemappingisassociatedto+*@dbi:doorbelldescriptor+*@map:trueifmapoperation,falseifunmapoperation+*+*Return:0onsuccessoranerrorcode+*/+staticintmsi_map_percpu_doorbell(structiommu_domain*domain,+conststructmsi_doorbell_info*dbi,boolmap)+{+intcpu,ret;++for_each_possible_cpu(cpu){+phys_addr_t__percpu*db_addr;+dma_addr_tiova;++db_addr=per_cpu_ptr(dbi->percpu_doorbells,cpu);++if(map){+ret=iommu_msi_get_doorbell_iova(domain,*db_addr,+dbi->size,dbi->prot,+&iova);+if(ret)+returnret;+}else{+iommu_msi_put_doorbell_iova(domain,*db_addr);+}+}+return0;+}++/**+*msi_handle_doorbell_mappings-IOMMUmap/unmapanyMSIdoorbellassociated+*totheirqdatahandle+*@data:irqdatahandle+*@map:trueifmapoperation,falseifunmapoperation+*+*IncasetheirqdatacorrespondstoanMSIsentbyadeviceinfrontof+*anIOMMUandthislatterdoesnotbypassMSItransactions,+*traversetheirqdomainhierarchytoretrievetheMSIdoorbellsand+*iommu_map/unmapthemaccordingto@mapboolean.+*+*Return0onsuccessorifnoactionisrequired,oranerrorcode+*/+staticintmsi_handle_doorbell_mappings(structirq_data*data,boolmap)+{+conststructmsi_doorbell_info*dbi;+structiommu_domain*domain;+structdevice*dev;++/* Is the MSI address translated by an IOMMU? */+dev=msi_desc_to_dev(irq_data_get_msi_desc(data));+domain=iommu_msi_domain(dev);+if(!domain)+return0;++/**+*DowefindadoorbelltoIOMMUmap?+*Ifwedon'teitherthedoorbellregistrationfailed,or+*theactualMSIcontrollerdidnotregisteritsdoorbell:+*eithertheMSIcontrollerisbehindtheIOMMUandtheMSI+*controllershouldhaveregistereditsdoorbell;ortheMSI+*controllerisinbetweenthedeviceandtheIOMMU.Wecurrently+*donotsupportthiscase.+*/+dbi=msi_get_doorbell_info(data);+if(!dbi)+return-ENODEV;++if(dbi->doorbell_is_percpu)+returnmsi_map_percpu_doorbell(domain,dbi,map);+else+returnmsi_map_global_doorbell(domain,dbi,map);+}++/***msi_domain_alloc_irqs-AllocateinterruptsfromaMSIinterruptdomain*@domain:Thedomaintoallocatefrom*@dev:Pointertodevicestructofthedeviceforwhichtheinterrupts
From: Eric Auger <eric.auger@redhat.com> Date: 2016-08-02 17:26:16
This new flags member is meant to store additional information about
the msi descriptor, starting with allocation status information.
MSI_DESC_FLAG_ALLOCATED bit tells the associated base IRQ is allocated.
This information is currently used at deallocation time. We also
introduce MSI_DESC_FLAG_FUNCTIONAL telling the MSIs are functional.
For the time being ALLOCATED and FUNCTIONAL are set at the same time
but this is going to change in subsequent patch. Indeed in some situations
some additional tasks need to be carried out for the MSI to be functional.
For instance the MSI doorbell may need to be mapped in an IOMMU.
FUNCTIONAL value already gets used when enumerating the usable MSIs in
msix_capability_init.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v12: new
---
drivers/pci/msi.c | 2 +-
include/linux/msi.h | 14 ++++++++++++++
kernel/irq/msi.c | 7 ++++++-
3 files changed, 21 insertions(+), 2 deletions(-)
From: Eric Auger <eric.auger@redhat.com> Date: 2016-08-02 17:27:50
Use the msi-doorbell API to register the global doorbell
and implement the irq_get_msi_doorbell_info
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v11 -> v12:
- use irq_get_msi_doorbell_info new name
- simplify error handling
v10 -> v11:
- use the new registration API and re-implement the msi_doorbell_info
ops
v9 -> v10:
- introduce the registration concept in place of msi_doorbell_info
callback
v8 -> v9:
- use global_doorbell instead of percpu_doorbells
v7 -> v8:
- gicv2m_msi_doorbell_info does not return a pointer to const
- remove spurious !v2m check
- add IOMMU_MMIO flag
v7: creation
---
drivers/irqchip/irq-gic-v2m.c | 35 ++++++++++++++++++++++++++++-------
1 file changed, 28 insertions(+), 7 deletions(-)
@@ -68,6 +70,7 @@ struct v2m_data {u32spi_offset;/* offset to be subtracted from SPI number */unsignedlong*bm;/* MSI vector bitmap */u32flags;/* v2m flags for specific implementation */+structmsi_doorbell_info*doorbell_info;/* MSI doorbell */};staticvoidgicv2m_mask_msi_irq(structirq_data*d)
From: Eric Auger <eric.auger@redhat.com> Date: 2016-08-02 17:28:03
Currently the msi_compose() uses the doorbell's physical address.
However in case the MSI doorbell is accessed through an IOMMU that
does not bypass the MSI transactions we need to use an IOVA instead.
iommu_msi_msg_pa_to_va helper, part of the iommu-msi API, detects
the above case and swaps the MSI doorbell physical address with a
pre-allocated/mapped IOVA.
That way the device will send the MSI with this IOVA and the address
will be translated by the IOMMU into the target MSI doorbell PA.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v11 -> v12:
- remove WARN_ON. iommu domain cannot dissapear while msi still are enabled
so the userspace cannot induce a kernel panic.
v8 -> v9:
- Braces on both sides of the 'else' in msi_compose
v7 -> v8:
- use iommu_msi_msg_pa_to_va
- add WARN_ON
v6 -> v7:
- allocation/mapping is done at an earlier stage. We now just perform
the iova lookup. So it is safe now to be called in a code that cannot
sleep. iommu_msi_set_doorbell_iova is moved in the dma-reserved-iommu
API: I think it cleans things up with respect to various #ifdef CONFIGS.
v5:
- use macros to increase the readability
- add comments
- fix a typo that caused a compilation error if CONFIG_IOMMU_API
is not set
---
kernel/irq/msi.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
From: Eric Auger <eric.auger@redhat.com> Date: 2016-08-02 17:42:42
msi_doorbell_safe returns whether all the registered doorbells
implement irq_remapping.
IRQ remapping is the x86 terminology (IRQ translation used on ARM).
The MSI controller topology is safe if all the registered doorbells
implement IRQ remapping.
This safety notion is used on ARM when assigning PCIe devices. If
any of the MSI doorbell is unsafe, the MSI assignment gets considered
unsafe.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v11 -> v12:
- reword the commit message
---
include/linux/msi-doorbell.h | 13 +++++++++++++
kernel/irq/msi-doorbell.c | 6 ++++++
2 files changed, 19 insertions(+)
@@ -130,3 +130,9 @@ int msi_doorbell_calc_pages(unsigned int order)returnret;}EXPORT_SYMBOL_GPL(msi_doorbell_calc_pages);++boolmsi_doorbell_safe(void)+{+return!nb_unsafe_doorbells;+}+EXPORT_SYMBOL_GPL(msi_doorbell_safe);
From: Eric Auger <eric.auger@redhat.com> Date: 2016-08-02 17:42:53
Currently the MSI message is composed by directly calling
irq_chip_compose_msi_msg and erased by setting the memory to zero.
On some platforms, we will need to complexify this composition to
properly handle MSI emission through IOMMU. Also we will need to track
when the MSI message is erased.
We propose to introduce a common wrapper for actual composition and
erasure, msi_compose.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v4 -> v5:
- just introduce the msi-compose wrapper without adding new
functionalities
v3 -> v4:
- that code was formely in irq-gic-common.c
"irqchip/gicv2m/v3-its-pci-msi: IOMMU map the MSI frame when needed"
also the [un]mapping was done in irq_write_msi_msg; now done on compose
v2 -> v3:
- protect iova/addr manipulation with CONFIG_ARCH_DMA_ADDR_T_64BIT and
CONFIG_PHYS_ADDR_T_64BIT
- only expose gic_pci_msi_domain_write_msg in case CONFIG_IOMMU_API &
CONFIG_PCI_MSI_IRQ_DOMAIN are set.
- gic_set/unset_msi_addr duly become static
---
kernel/irq/msi.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
From: Eric Auger <eric.auger@redhat.com> Date: 2016-08-02 18:20:51
From: Eric Auger <redacted>
The purpose is to be able to retrieve the MSI doorbells of an irqchip.
This is now needed since on some platforms those doorbells must be
iommu mapped (in case the MSIs transit through an IOMMU that do not
bypass those transactions).
The assumption is there is a maximum of one doorbell region per cpu. The
doorbell can be global or per cpu.
A doorbell region is characterized by its physical address base, size,
IOMMU protection flag and whether it implements IRQ remapping (aka.
IRQ translation). Those characteristics are shared among all doorbells.
irq_get_msi_doorbell_info callback enables to retrieve the doorbells of
the irqchip.
Signed-off-by: Eric Auger <redacted>
---
v11 -> v12:
- remove tail comments and do proper kernel doc ones
- align struct members
- rename msi_doorbell_info into irq_get_msi_doorbell_info
- remove line break
v10 -> v11:
- disappeared in V10 and restored now. struct irq_chip_msi_doorbell_info
is identifical to the one in V10 (union, irq_remapping field).
v7 -> v8:
- size and prot now are shared among all doorbells
- doorbells now directly points to a percpu phys_addr_t
v7: creation
---
include/linux/irq.h | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
From: Eric Auger <eric.auger@redhat.com> Date: 2016-08-02 19:18:45
msi_doorbell_calc_pages() sum up the number of iommu pages of a given order
requested to map all the registered doorbells. This function will allow
to dimension the intermediate physical address (IPA) aperture requested
to map the MSI doorbells.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v11 -> v12:
- fix style issues: remove useless line break, remove pointless braces,
fix kernel-doc comments
- reword commit message
- rename msi_doorbell_pages into msi_doorbell_calc_pages
- rename static compute* functions
v10: creation
---
include/linux/msi-doorbell.h | 14 ++++++++++
kernel/irq/msi-doorbell.c | 64 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 78 insertions(+)
From: Eric Auger <eric.auger@redhat.com> Date: 2016-08-02 20:29:37
This new API aims at allowing irqchips to allocate & register
the MSI doorbells likely to be iommu mapped.
Later on, other services will be added allowing the VFIO layer
to query information based on all registered doorbells.
We count the number of doorbells that do not implement IRQ
remapping. They will be considered as unsafe with respect to MSI
assignment.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v11 -> v12:
- rename irqchip_doorbell into msi_doorbell, irqchip_doorbell_list
into msi_doorbell_list and irqchip_doorbell_mutex into
msi_doorbell_mutex
- fix style issues: align msi_doorbell struct members, kernel-doc comments
- use kzalloc
- use container_of in msi_doorbell_unregister_global
- compute nb_unsafe_doorbells on registration/unregistration
- registration simply returns NULL if allocation failed
v10 -> v11:
- remove void *chip_data argument from register/unregister function
- remove lookup funtions since we restored the struct irq_chip
msi_doorbell_info ops to realize this function
- reword commit message and title
---
drivers/iommu/Kconfig | 1 +
include/linux/msi-doorbell.h | 55 +++++++++++++++++++++++++++++++++++
kernel/irq/Kconfig | 4 +++
kernel/irq/Makefile | 1 +
kernel/irq/msi-doorbell.c | 68 ++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 129 insertions(+)
create mode 100644 include/linux/msi-doorbell.h
create mode 100644 kernel/irq/msi-doorbell.c
@@ -0,0 +1,68 @@+/*+*linux/kernel/irq/msi-doorbell.c+*+*Copyright(C)2016Linaro+*Author:EricAuger<eric.auger@linaro.org>+*+*ThisfileislicensedunderGPLv2.+*+*ThisfilecontainscommoncodetomanageMSIdoorbellslikely+*tobeiommumapped.TypicallymeaningfulonARM.+*/++#include<linux/slab.h>+#include<linux/irq.h>+#include<linux/msi-doorbell.h>++structmsi_doorbell{+structmsi_doorbell_infoinfo;+structlist_headnext;+};++/* list of registered MSI doorbells */+staticLIST_HEAD(msi_doorbell_list);++/* counts the number of unsafe registered doorbells */+staticuintnb_unsafe_doorbells;++/* protects the list and nb__unsafe_doorbells */+staticDEFINE_MUTEX(msi_doorbell_mutex);++structmsi_doorbell_info*+msi_doorbell_register_global(phys_addr_tbase,size_tsize,+intprot,boolirq_remapping)+{+structmsi_doorbell*db;++db=kzalloc(sizeof(*db),GFP_KERNEL);+if(!db)+returnNULL;++db->info.global_doorbell=base;+db->info.size=size;+db->info.prot=prot;+db->info.irq_remapping=irq_remapping;++mutex_lock(&msi_doorbell_mutex);+list_add(&db->next,&msi_doorbell_list);+if(!db->info.irq_remapping)+nb_unsafe_doorbells++;+mutex_unlock(&msi_doorbell_mutex);+return&db->info;+}+EXPORT_SYMBOL_GPL(msi_doorbell_register_global);++voidmsi_doorbell_unregister_global(structmsi_doorbell_info*dbinfo)+{+structmsi_doorbell*db;++db=container_of(dbinfo,structmsi_doorbell,info);++mutex_lock(&msi_doorbell_mutex);+list_del(&db->next);+if(!db->info.irq_remapping)+nb_unsafe_doorbells--;+mutex_unlock(&msi_doorbell_mutex);+kfree(db);+}+EXPORT_SYMBOL_GPL(msi_doorbell_unregister_global);
From: Auger Eric <eric.auger@redhat.com> Date: 2016-08-09 06:52:32
Hi,
On 02/08/2016 19:23, Eric Auger wrote:
quoted hunk
This new flags member is meant to store additional information about
the msi descriptor, starting with allocation status information.
MSI_DESC_FLAG_ALLOCATED bit tells the associated base IRQ is allocated.
This information is currently used at deallocation time. We also
introduce MSI_DESC_FLAG_FUNCTIONAL telling the MSIs are functional.
For the time being ALLOCATED and FUNCTIONAL are set at the same time
but this is going to change in subsequent patch. Indeed in some situations
some additional tasks need to be carried out for the MSI to be functional.
For instance the MSI doorbell may need to be mapped in an IOMMU.
FUNCTIONAL value already gets used when enumerating the usable MSIs in
msix_capability_init.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v12: new
---
drivers/pci/msi.c | 2 +-
include/linux/msi.h | 14 ++++++++++++++
kernel/irq/msi.c | 7 ++++++-
3 files changed, 21 insertions(+), 2 deletions(-)
@@ -99,6 +101,18 @@ struct msi_desc { }; };+/* Flags for msi_desc */+enum {+ /* the base IRQ is allocated */+ MSI_DESC_FLAG_ALLOCATED = (1 << 0),+ /**+ * the MSI is functional; in some cases the fact the base IRQ is+ * allocated is not sufficient for the MSIs to be functional: for+ * example the MSI doorbell(s) may need to be IOMMU mapped.+ */+ MSI_DESC_FLAG_FUNCTIONAL = (1 << 1),+};+ /* Helpers to hide struct msi_desc implementation details */ #define msi_desc_to_dev(desc) ((desc)->dev) #define dev_to_msi_list(dev) (&(dev)->msi_list)
From: Thomas Gleixner <hidden> Date: 2016-08-09 09:22:02
On Tue, 2 Aug 2016, Eric Auger wrote:
Currently the MSI message is composed by directly calling
irq_chip_compose_msi_msg and erased by setting the memory to zero.
On some platforms, we will need to complexify this composition to
properly handle MSI emission through IOMMU. Also we will need to track
when the MSI message is erased.
I just can't find how you do that. After applying the series the
+ if (erase)
+ memset(msg, 0, sizeof(*msg));
branch is still just a memset(). The wrapper is fine for the compose side, but
having the extra argument just to wrap the memset() for no gain is silly.
Thanks,
tglx
From: Auger Eric <eric.auger@redhat.com> Date: 2016-08-10 18:16:26
Hi Thomas,
On 09/08/2016 11:19, Thomas Gleixner wrote:
On Tue, 2 Aug 2016, Eric Auger wrote:
quoted
Currently the MSI message is composed by directly calling
irq_chip_compose_msi_msg and erased by setting the memory to zero.
On some platforms, we will need to complexify this composition to
properly handle MSI emission through IOMMU. Also we will need to track
when the MSI message is erased.
I just can't find how you do that. After applying the series the
quoted
+ if (erase)
+ memset(msg, 0, sizeof(*msg));
branch is still just a memset(). The wrapper is fine for the compose side, but
having the extra argument just to wrap the memset() for no gain is silly.
Yes you're right: this was true in the first releases of the series
where the iommu mapping/unmapping were done at composition & erase time.
Now the mapping/unmapping is done on msi_domain_alloc/free_irqs, this is
not mandated anymore. I will keep the wrapper for the compose side and
remove the rest + update the commit message accordingly.
Thank you for your time.
Eric
Thanks,
tglx
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html