diff mbox series

[RFC,v2,08/22] intel_iommu: provide get_iommu_context() callback

Message ID 1571920483-3382-9-git-send-email-yi.l.liu@intel.com (mailing list archive)
State New, archived
Headers show
Series intel_iommu: expose Shared Virtual Addressing to VM | expand

Commit Message

Yi Liu Oct. 24, 2019, 12:34 p.m. UTC
This patch adds get_iommu_context() callback to return an iommu_context
Intel VT-d platform.

Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Yi Sun <yi.y.sun@linux.intel.com>
Signed-off-by: Liu Yi L <yi.l.liu@intel.com>
---
 hw/i386/intel_iommu.c         | 57 ++++++++++++++++++++++++++++++++++++++-----
 include/hw/i386/intel_iommu.h | 14 ++++++++++-
 2 files changed, 64 insertions(+), 7 deletions(-)

Comments

Peter Xu Nov. 1, 2019, 2:55 p.m. UTC | #1
On Thu, Oct 24, 2019 at 08:34:29AM -0400, Liu Yi L wrote:
> This patch adds get_iommu_context() callback to return an iommu_context
> Intel VT-d platform.
> 
> Cc: Kevin Tian <kevin.tian@intel.com>
> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
> Cc: Peter Xu <peterx@redhat.com>
> Cc: Yi Sun <yi.y.sun@linux.intel.com>
> Signed-off-by: Liu Yi L <yi.l.liu@intel.com>
> ---
>  hw/i386/intel_iommu.c         | 57 ++++++++++++++++++++++++++++++++++++++-----
>  include/hw/i386/intel_iommu.h | 14 ++++++++++-
>  2 files changed, 64 insertions(+), 7 deletions(-)
> 
> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
> index 67a7836..e9f8692 100644
> --- a/hw/i386/intel_iommu.c
> +++ b/hw/i386/intel_iommu.c
> @@ -3288,22 +3288,33 @@ static const MemoryRegionOps vtd_mem_ir_ops = {
>      },
>  };
>  
> -VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
> +static VTDBus *vtd_find_add_bus(IntelIOMMUState *s, PCIBus *bus)
>  {
>      uintptr_t key = (uintptr_t)bus;
> -    VTDBus *vtd_bus = g_hash_table_lookup(s->vtd_as_by_busptr, &key);
> -    VTDAddressSpace *vtd_dev_as;
> -    char name[128];
> +    VTDBus *vtd_bus;
>  
> +    vtd_iommu_lock(s);

Why explicitly take the IOMMU lock here?  I mean, it's fine to take
it, but if so why not take it to cover the whole vtd_find_add_as()?

For now it'll be fine in either way because I believe iommu_lock is
not really functioning when we're still with BQL here, however if you
add that explicitly then I don't see why it's not covering that.

> +    vtd_bus = g_hash_table_lookup(s->vtd_as_by_busptr, &key);
>      if (!vtd_bus) {
>          uintptr_t *new_key = g_malloc(sizeof(*new_key));
>          *new_key = (uintptr_t)bus;
>          /* No corresponding free() */
> -        vtd_bus = g_malloc0(sizeof(VTDBus) + sizeof(VTDAddressSpace *) * \
> -                            PCI_DEVFN_MAX);
> +        vtd_bus = g_malloc0(sizeof(VTDBus) + PCI_DEVFN_MAX * \
> +                    (sizeof(VTDAddressSpace *) + sizeof(VTDIOMMUContext *)));

Should this be as simple as g_malloc0(sizeof(VTDBus) since [1]?

Otherwise the patch looks sane to me.

>          vtd_bus->bus = bus;
>          g_hash_table_insert(s->vtd_as_by_busptr, new_key, vtd_bus);
>      }
> +    vtd_iommu_unlock(s);
> +    return vtd_bus;
> +}

[...]

>  struct VTDBus {
>      PCIBus* bus;		/* A reference to the bus to provide translation for */
> -    VTDAddressSpace *dev_as[0];	/* A table of VTDAddressSpace objects indexed by devfn */
> +    /* A table of VTDAddressSpace objects indexed by devfn */
> +    VTDAddressSpace *dev_as[PCI_DEVFN_MAX];
> +    /* A table of VTDIOMMUContext objects indexed by devfn */
> +    VTDIOMMUContext *dev_ic[PCI_DEVFN_MAX];

[1]

>  };
>  
>  struct VTDIOTLBEntry {
> @@ -282,5 +293,6 @@ struct IntelIOMMUState {
>   * create a new one if none exists
>   */
>  VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn);
> +VTDIOMMUContext *vtd_find_add_ic(IntelIOMMUState *s, PCIBus *bus, int devfn);
>  
>  #endif
> -- 
> 2.7.4
> 

Regards,
Yi Liu Nov. 6, 2019, 11:07 a.m. UTC | #2
> From: Peter Xu [mailto:peterx@redhat.com]
> Sent: Friday, November 1, 2019 10:55 PM
> To: Liu, Yi L <yi.l.liu@intel.com>
> Subject: Re: [RFC v2 08/22] intel_iommu: provide get_iommu_context() callback
> 
> On Thu, Oct 24, 2019 at 08:34:29AM -0400, Liu Yi L wrote:
> > This patch adds get_iommu_context() callback to return an iommu_context
> > Intel VT-d platform.
> >
> > Cc: Kevin Tian <kevin.tian@intel.com>
> > Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
> > Cc: Peter Xu <peterx@redhat.com>
> > Cc: Yi Sun <yi.y.sun@linux.intel.com>
> > Signed-off-by: Liu Yi L <yi.l.liu@intel.com>
> > ---
> >  hw/i386/intel_iommu.c         | 57 ++++++++++++++++++++++++++++++++++++++---
> --
> >  include/hw/i386/intel_iommu.h | 14 ++++++++++-
> >  2 files changed, 64 insertions(+), 7 deletions(-)
> >
> > diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
> > index 67a7836..e9f8692 100644
> > --- a/hw/i386/intel_iommu.c
> > +++ b/hw/i386/intel_iommu.c
> > @@ -3288,22 +3288,33 @@ static const MemoryRegionOps vtd_mem_ir_ops = {
> >      },
> >  };
> >
> > -VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
> > +static VTDBus *vtd_find_add_bus(IntelIOMMUState *s, PCIBus *bus)
> >  {
> >      uintptr_t key = (uintptr_t)bus;
> > -    VTDBus *vtd_bus = g_hash_table_lookup(s->vtd_as_by_busptr, &key);
> > -    VTDAddressSpace *vtd_dev_as;
> > -    char name[128];
> > +    VTDBus *vtd_bus;
> >
> > +    vtd_iommu_lock(s);
> 
> Why explicitly take the IOMMU lock here?  I mean, it's fine to take
> it, but if so why not take it to cover the whole vtd_find_add_as()?

Just wanted to make the protected snippet smaller. But I'm fine to move it
to vtd_find_add_as() if there is no much value for putting it here.

> For now it'll be fine in either way because I believe iommu_lock is
> not really functioning when we're still with BQL here, however if you
> add that explicitly then I don't see why it's not covering that.

Got it. It functions if you missed to put a mirrored unlock after a lock. (joke)

> 
> > +    vtd_bus = g_hash_table_lookup(s->vtd_as_by_busptr, &key);
> >      if (!vtd_bus) {
> >          uintptr_t *new_key = g_malloc(sizeof(*new_key));
> >          *new_key = (uintptr_t)bus;
> >          /* No corresponding free() */
> > -        vtd_bus = g_malloc0(sizeof(VTDBus) + sizeof(VTDAddressSpace *) * \
> > -                            PCI_DEVFN_MAX);
> > +        vtd_bus = g_malloc0(sizeof(VTDBus) + PCI_DEVFN_MAX * \
> > +                    (sizeof(VTDAddressSpace *) + sizeof(VTDIOMMUContext *)));
> 
> Should this be as simple as g_malloc0(sizeof(VTDBus) since [1]?

yes, it's old writing. Will modify it.

> Otherwise the patch looks sane to me.
> 
> >          vtd_bus->bus = bus;
> >          g_hash_table_insert(s->vtd_as_by_busptr, new_key, vtd_bus);
> >      }
> > +    vtd_iommu_unlock(s);
> > +    return vtd_bus;
> > +}
> 
> [...]
> 
> >  struct VTDBus {
> >      PCIBus* bus;		/* A reference to the bus to provide translation for
> */
> > -    VTDAddressSpace *dev_as[0];	/* A table of VTDAddressSpace objects
> indexed by devfn */
> > +    /* A table of VTDAddressSpace objects indexed by devfn */
> > +    VTDAddressSpace *dev_as[PCI_DEVFN_MAX];
> > +    /* A table of VTDIOMMUContext objects indexed by devfn */
> > +    VTDIOMMUContext *dev_ic[PCI_DEVFN_MAX];
> 
> [1]

exactly.

> 
> >  };
> >
> >  struct VTDIOTLBEntry {
> > @@ -282,5 +293,6 @@ struct IntelIOMMUState {
> >   * create a new one if none exists
> >   */
> >  VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn);
> > +VTDIOMMUContext *vtd_find_add_ic(IntelIOMMUState *s, PCIBus *bus, int
> devfn);
> >
> >  #endif
> > --
> > 2.7.4
> >

Thanks,
Yi Liu
diff mbox series

Patch

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 67a7836..e9f8692 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3288,22 +3288,33 @@  static const MemoryRegionOps vtd_mem_ir_ops = {
     },
 };
 
-VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
+static VTDBus *vtd_find_add_bus(IntelIOMMUState *s, PCIBus *bus)
 {
     uintptr_t key = (uintptr_t)bus;
-    VTDBus *vtd_bus = g_hash_table_lookup(s->vtd_as_by_busptr, &key);
-    VTDAddressSpace *vtd_dev_as;
-    char name[128];
+    VTDBus *vtd_bus;
 
+    vtd_iommu_lock(s);
+    vtd_bus = g_hash_table_lookup(s->vtd_as_by_busptr, &key);
     if (!vtd_bus) {
         uintptr_t *new_key = g_malloc(sizeof(*new_key));
         *new_key = (uintptr_t)bus;
         /* No corresponding free() */
-        vtd_bus = g_malloc0(sizeof(VTDBus) + sizeof(VTDAddressSpace *) * \
-                            PCI_DEVFN_MAX);
+        vtd_bus = g_malloc0(sizeof(VTDBus) + PCI_DEVFN_MAX * \
+                    (sizeof(VTDAddressSpace *) + sizeof(VTDIOMMUContext *)));
         vtd_bus->bus = bus;
         g_hash_table_insert(s->vtd_as_by_busptr, new_key, vtd_bus);
     }
+    vtd_iommu_unlock(s);
+    return vtd_bus;
+}
+
+VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
+{
+    VTDBus *vtd_bus;
+    VTDAddressSpace *vtd_dev_as;
+    char name[128];
+
+    vtd_bus = vtd_find_add_bus(s, bus);
 
     vtd_dev_as = vtd_bus->dev_as[devfn];
 
@@ -3370,6 +3381,27 @@  VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
     return vtd_dev_as;
 }
 
+VTDIOMMUContext *vtd_find_add_ic(IntelIOMMUState *s,
+                                 PCIBus *bus, int devfn)
+{
+    VTDBus *vtd_bus;
+    VTDIOMMUContext *vtd_dev_ic;
+
+    vtd_bus = vtd_find_add_bus(s, bus);
+
+    vtd_dev_ic = vtd_bus->dev_ic[devfn];
+
+    if (!vtd_dev_ic) {
+        vtd_bus->dev_ic[devfn] = vtd_dev_ic =
+                    g_malloc0(sizeof(VTDIOMMUContext));
+        vtd_dev_ic->vtd_bus = vtd_bus;
+        vtd_dev_ic->devfn = (uint8_t)devfn;
+        vtd_dev_ic->iommu_state = s;
+        iommu_context_init(&vtd_dev_ic->iommu_context);
+    }
+    return vtd_dev_ic;
+}
+
 static uint64_t get_naturally_aligned_size(uint64_t start,
                                            uint64_t size, int gaw)
 {
@@ -3666,8 +3698,21 @@  static AddressSpace *vtd_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
     return &vtd_as->as;
 }
 
+static IOMMUContext *vtd_dev_iommu_context(PCIBus *bus,
+                                           void *opaque, int devfn)
+{
+    IntelIOMMUState *s = opaque;
+    VTDIOMMUContext *vtd_ic;
+
+    assert(0 <= devfn && devfn < PCI_DEVFN_MAX);
+
+    vtd_ic = vtd_find_add_ic(s, bus, devfn);
+    return &vtd_ic->iommu_context;
+}
+
 static PCIIOMMUOps vtd_iommu_ops = {
     .get_address_space = vtd_host_dma_iommu,
+    .get_iommu_context = vtd_dev_iommu_context,
 };
 
 static bool vtd_decide_config(IntelIOMMUState *s, Error **errp)
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 6062588..1c580c1 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -68,6 +68,7 @@  typedef union VTD_IR_TableEntry VTD_IR_TableEntry;
 typedef union VTD_IR_MSIAddress VTD_IR_MSIAddress;
 typedef struct VTDPASIDDirEntry VTDPASIDDirEntry;
 typedef struct VTDPASIDEntry VTDPASIDEntry;
+typedef struct VTDIOMMUContext VTDIOMMUContext;
 
 /* Context-Entry */
 struct VTDContextEntry {
@@ -116,9 +117,19 @@  struct VTDAddressSpace {
     IOVATree *iova_tree;          /* Traces mapped IOVA ranges */
 };
 
+struct VTDIOMMUContext {
+    VTDBus *vtd_bus;
+    uint8_t devfn;
+    IOMMUContext iommu_context;
+    IntelIOMMUState *iommu_state;
+};
+
 struct VTDBus {
     PCIBus* bus;		/* A reference to the bus to provide translation for */
-    VTDAddressSpace *dev_as[0];	/* A table of VTDAddressSpace objects indexed by devfn */
+    /* A table of VTDAddressSpace objects indexed by devfn */
+    VTDAddressSpace *dev_as[PCI_DEVFN_MAX];
+    /* A table of VTDIOMMUContext objects indexed by devfn */
+    VTDIOMMUContext *dev_ic[PCI_DEVFN_MAX];
 };
 
 struct VTDIOTLBEntry {
@@ -282,5 +293,6 @@  struct IntelIOMMUState {
  * create a new one if none exists
  */
 VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn);
+VTDIOMMUContext *vtd_find_add_ic(IntelIOMMUState *s, PCIBus *bus, int devfn);
 
 #endif