RE: [PATCH v1 12/22] intel_iommu: add PASID cache management infrastructure

2020-03-26 Thread Liu, Yi L
> From: Peter Xu 
> Sent: Thursday, March 26, 2020 11:54 PM
> To: Liu, Yi L 
> Subject: Re: [PATCH v1 12/22] intel_iommu: add PASID cache management
> infrastructure
> 
> On Thu, Mar 26, 2020 at 01:57:10PM +, Liu, Yi L wrote:
> > > From: Liu, Yi L
> > > Sent: Thursday, March 26, 2020 2:15 PM
> > > To: 'Peter Xu' 
> > > Subject: RE: [PATCH v1 12/22] intel_iommu: add PASID cache management
> > > infrastructure
> > >
> > > > From: Peter Xu 
> > > > Sent: Wednesday, March 25, 2020 10:52 PM
> > > > To: Liu, Yi L 
> > > > Subject: Re: [PATCH v1 12/22] intel_iommu: add PASID cache management
> > > > infrastructure
> > > >
> > > > On Wed, Mar 25, 2020 at 12:20:21PM +0000, Liu, Yi L wrote:
> > > > > > From: Peter Xu 
> > > > > > Sent: Wednesday, March 25, 2020 1:32 AM
> > > > > > To: Liu, Yi L 
> > > > > > Subject: Re: [PATCH v1 12/22] intel_iommu: add PASID cache
> > > > > > management infrastructure
> > > > > >
> > > > > > On Sun, Mar 22, 2020 at 05:36:09AM -0700, Liu Yi L wrote:
> > > > > > > This patch adds a PASID cache management infrastructure based on
> > > > > > > new added structure VTDPASIDAddressSpace, which is used to track
> > > > > > > the PASID usage and future PASID tagged DMA address translation
> > > > > > > support in vIOMMU.
> > [...]
> > > > > >
> > > > > > 
> > > > > >
> > > > > > > +/*
> > > > > > > + * Step 2: loop all the exisitng vtd_dev_icx instances.
> > > > > > > + * Ideally, needs to loop all devices to find if there is 
> > > > > > > any new
> > > > > > > + * PASID binding regards to the PASID cache invalidation 
> > > > > > > request.
> > > > > > > + * But it is enough to loop the devices which are backed by 
> > > > > > > host
> > > > > > > + * IOMMU. For devices backed by vIOMMU (a.k.a emulated 
> > > > > > > devices),
> > > > > > > + * if new PASID happened on them, their vtd_pasid_as 
> > > > > > > instance could
> > > > > > > + * be created during future vIOMMU DMA translation.
> > > > > > > + */
> > > > > > > +QLIST_FOREACH(vtd_dev_icx, >vtd_dev_icx_list, next) {
> > > > > > > +VTDPASIDAddressSpace *vtd_pasid_as;
> > > > > > > +VTDPASIDCacheEntry *pc_entry;
> > > > > > > +VTDPASIDEntry pe;
> > > > > > > +VTDBus *vtd_bus = vtd_dev_icx->vtd_bus;
> > > > > > > +uint16_t devfn = vtd_dev_icx->devfn;
> > > > > > > +int bus_n = pci_bus_num(vtd_bus->bus);
> > > > > > > +
> > > > > > > +/* i) fetch vtd_pasid_as and check if it is valid */
> > > > > > > +vtd_pasid_as = vtd_add_find_pasid_as(s, vtd_bus,
> > > > > > > + devfn, pasid);
> > > > > >
> > > > > > I don't feel like it's correct here...
> > > > > >
> > > > > > Assuming we have two devices assigned D1, D2.  D1 uses PASID=1, D2
> > > > > > uses
> > > > PASID=2.
> > > > > > When invalidating against PASID=1, are you also going to create a
> > > > > > VTDPASIDAddressSpace also for D2 with PASID=1?
> > > > >
> > > > > Answer is no. Before going forward, let's see if the below flow looks 
> > > > > good to
> you.
> > > > >
> > > > > Let me add one more device besides D1 and D2. Say device D3 which
> > > > > also uses PASID=1. And assume it begins with no PASID usage in guest.
> > > > >
> > > > > Then the flow from scratch is:
> > > > >
> > > > > a) guest IOMMU driver setup PASID entry for D1 with PASID=1,
> > > > >then invalidates against PASID #1
> > > > > b) trap to QEMU, and comes to this function. Since there is
> > > > >no previous pasid cache invalidation, so the Step 1 of this
> > > > >function has nothing to do, then goes to Step 2 which is to
> > > > 

Re: [PATCH v1 12/22] intel_iommu: add PASID cache management infrastructure

2020-03-26 Thread Peter Xu
On Thu, Mar 26, 2020 at 01:57:10PM +, Liu, Yi L wrote:
> > From: Liu, Yi L
> > Sent: Thursday, March 26, 2020 2:15 PM
> > To: 'Peter Xu' 
> > Subject: RE: [PATCH v1 12/22] intel_iommu: add PASID cache management
> > infrastructure
> > 
> > > From: Peter Xu 
> > > Sent: Wednesday, March 25, 2020 10:52 PM
> > > To: Liu, Yi L 
> > > Subject: Re: [PATCH v1 12/22] intel_iommu: add PASID cache management
> > > infrastructure
> > >
> > > On Wed, Mar 25, 2020 at 12:20:21PM +, Liu, Yi L wrote:
> > > > > From: Peter Xu 
> > > > > Sent: Wednesday, March 25, 2020 1:32 AM
> > > > > To: Liu, Yi L 
> > > > > Subject: Re: [PATCH v1 12/22] intel_iommu: add PASID cache
> > > > > management infrastructure
> > > > >
> > > > > On Sun, Mar 22, 2020 at 05:36:09AM -0700, Liu Yi L wrote:
> > > > > > This patch adds a PASID cache management infrastructure based on
> > > > > > new added structure VTDPASIDAddressSpace, which is used to track
> > > > > > the PASID usage and future PASID tagged DMA address translation
> > > > > > support in vIOMMU.
> [...]
> > > > >
> > > > > 
> > > > >
> > > > > > +/*
> > > > > > + * Step 2: loop all the exisitng vtd_dev_icx instances.
> > > > > > + * Ideally, needs to loop all devices to find if there is any 
> > > > > > new
> > > > > > + * PASID binding regards to the PASID cache invalidation 
> > > > > > request.
> > > > > > + * But it is enough to loop the devices which are backed by 
> > > > > > host
> > > > > > + * IOMMU. For devices backed by vIOMMU (a.k.a emulated 
> > > > > > devices),
> > > > > > + * if new PASID happened on them, their vtd_pasid_as instance 
> > > > > > could
> > > > > > + * be created during future vIOMMU DMA translation.
> > > > > > + */
> > > > > > +QLIST_FOREACH(vtd_dev_icx, >vtd_dev_icx_list, next) {
> > > > > > +VTDPASIDAddressSpace *vtd_pasid_as;
> > > > > > +VTDPASIDCacheEntry *pc_entry;
> > > > > > +VTDPASIDEntry pe;
> > > > > > +VTDBus *vtd_bus = vtd_dev_icx->vtd_bus;
> > > > > > +uint16_t devfn = vtd_dev_icx->devfn;
> > > > > > +int bus_n = pci_bus_num(vtd_bus->bus);
> > > > > > +
> > > > > > +/* i) fetch vtd_pasid_as and check if it is valid */
> > > > > > +vtd_pasid_as = vtd_add_find_pasid_as(s, vtd_bus,
> > > > > > + devfn, pasid);
> > > > >
> > > > > I don't feel like it's correct here...
> > > > >
> > > > > Assuming we have two devices assigned D1, D2.  D1 uses PASID=1, D2
> > > > > uses
> > > PASID=2.
> > > > > When invalidating against PASID=1, are you also going to create a
> > > > > VTDPASIDAddressSpace also for D2 with PASID=1?
> > > >
> > > > Answer is no. Before going forward, let's see if the below flow looks 
> > > > good to you.
> > > >
> > > > Let me add one more device besides D1 and D2. Say device D3 which
> > > > also uses PASID=1. And assume it begins with no PASID usage in guest.
> > > >
> > > > Then the flow from scratch is:
> > > >
> > > > a) guest IOMMU driver setup PASID entry for D1 with PASID=1,
> > > >then invalidates against PASID #1
> > > > b) trap to QEMU, and comes to this function. Since there is
> > > >no previous pasid cache invalidation, so the Step 1 of this
> > > >function has nothing to do, then goes to Step 2 which is to
> > > >loop all assigned devices and check if the guest pasid entry
> > > >is present. In this loop, should find D1's pasid entry for
> > > >PASID#1 is present. So create the VTDPASIDAddressSpace and
> > > >initialize its pasid_cache_entry and pasid_cache_gen fields.
> > > > c) guest IOMMU driver setup PASID entry for D2 with PASID=2,
> > > >then invalidates against PASID #2
> > > > d) same with b), only difference is the Step 1 of this function
> > > >will loop the VTDPASIDAd

RE: [PATCH v1 12/22] intel_iommu: add PASID cache management infrastructure

2020-03-26 Thread Liu, Yi L
> From: Liu, Yi L
> Sent: Thursday, March 26, 2020 2:15 PM
> To: 'Peter Xu' 
> Subject: RE: [PATCH v1 12/22] intel_iommu: add PASID cache management
> infrastructure
> 
> > From: Peter Xu 
> > Sent: Wednesday, March 25, 2020 10:52 PM
> > To: Liu, Yi L 
> > Subject: Re: [PATCH v1 12/22] intel_iommu: add PASID cache management
> > infrastructure
> >
> > On Wed, Mar 25, 2020 at 12:20:21PM +, Liu, Yi L wrote:
> > > > From: Peter Xu 
> > > > Sent: Wednesday, March 25, 2020 1:32 AM
> > > > To: Liu, Yi L 
> > > > Subject: Re: [PATCH v1 12/22] intel_iommu: add PASID cache
> > > > management infrastructure
> > > >
> > > > On Sun, Mar 22, 2020 at 05:36:09AM -0700, Liu Yi L wrote:
> > > > > This patch adds a PASID cache management infrastructure based on
> > > > > new added structure VTDPASIDAddressSpace, which is used to track
> > > > > the PASID usage and future PASID tagged DMA address translation
> > > > > support in vIOMMU.
[...]
> > > >
> > > > 
> > > >
> > > > > +/*
> > > > > + * Step 2: loop all the exisitng vtd_dev_icx instances.
> > > > > + * Ideally, needs to loop all devices to find if there is any new
> > > > > + * PASID binding regards to the PASID cache invalidation request.
> > > > > + * But it is enough to loop the devices which are backed by host
> > > > > + * IOMMU. For devices backed by vIOMMU (a.k.a emulated devices),
> > > > > + * if new PASID happened on them, their vtd_pasid_as instance 
> > > > > could
> > > > > + * be created during future vIOMMU DMA translation.
> > > > > + */
> > > > > +QLIST_FOREACH(vtd_dev_icx, >vtd_dev_icx_list, next) {
> > > > > +VTDPASIDAddressSpace *vtd_pasid_as;
> > > > > +VTDPASIDCacheEntry *pc_entry;
> > > > > +VTDPASIDEntry pe;
> > > > > +VTDBus *vtd_bus = vtd_dev_icx->vtd_bus;
> > > > > +uint16_t devfn = vtd_dev_icx->devfn;
> > > > > +int bus_n = pci_bus_num(vtd_bus->bus);
> > > > > +
> > > > > +/* i) fetch vtd_pasid_as and check if it is valid */
> > > > > +vtd_pasid_as = vtd_add_find_pasid_as(s, vtd_bus,
> > > > > + devfn, pasid);
> > > >
> > > > I don't feel like it's correct here...
> > > >
> > > > Assuming we have two devices assigned D1, D2.  D1 uses PASID=1, D2
> > > > uses
> > PASID=2.
> > > > When invalidating against PASID=1, are you also going to create a
> > > > VTDPASIDAddressSpace also for D2 with PASID=1?
> > >
> > > Answer is no. Before going forward, let's see if the below flow looks 
> > > good to you.
> > >
> > > Let me add one more device besides D1 and D2. Say device D3 which
> > > also uses PASID=1. And assume it begins with no PASID usage in guest.
> > >
> > > Then the flow from scratch is:
> > >
> > > a) guest IOMMU driver setup PASID entry for D1 with PASID=1,
> > >then invalidates against PASID #1
> > > b) trap to QEMU, and comes to this function. Since there is
> > >no previous pasid cache invalidation, so the Step 1 of this
> > >function has nothing to do, then goes to Step 2 which is to
> > >loop all assigned devices and check if the guest pasid entry
> > >is present. In this loop, should find D1's pasid entry for
> > >PASID#1 is present. So create the VTDPASIDAddressSpace and
> > >initialize its pasid_cache_entry and pasid_cache_gen fields.
> > > c) guest IOMMU driver setup PASID entry for D2 with PASID=2,
> > >then invalidates against PASID #2
> > > d) same with b), only difference is the Step 1 of this function
> > >will loop the VTDPASIDAddressSpace created in b), but its
> > >pasid is 1 which is not the target of current pasid cache
> > >invalidation. Same with b), in Step 2, it will create a
> > >VTDPASIDAddressSpace for D2+PASID#2
> > > e) guest IOMMU driver setup PASID entry for D3 with PASID=1,
> > >then invalidates against PASID #1
> > > f) trap to QEMU and comes to this function. Step 1 loops two
> > >VTDPASIDAddressSpace created in b) and d), and it finds there
> > >is a VTDPASIDAddressSpac

RE: [PATCH v1 12/22] intel_iommu: add PASID cache management infrastructure

2020-03-26 Thread Liu, Yi L
> From: Peter Xu 
> Sent: Wednesday, March 25, 2020 10:52 PM
> To: Liu, Yi L 
> Subject: Re: [PATCH v1 12/22] intel_iommu: add PASID cache management
> infrastructure
> 
> On Wed, Mar 25, 2020 at 12:20:21PM +, Liu, Yi L wrote:
> > > From: Peter Xu 
> > > Sent: Wednesday, March 25, 2020 1:32 AM
> > > To: Liu, Yi L 
> > > Subject: Re: [PATCH v1 12/22] intel_iommu: add PASID cache management
> > > infrastructure
> > >
> > > On Sun, Mar 22, 2020 at 05:36:09AM -0700, Liu Yi L wrote:
> > > > This patch adds a PASID cache management infrastructure based on new
> > > > added structure VTDPASIDAddressSpace, which is used to track the PASID
> > > > usage and future PASID tagged DMA address translation support in
> > > > vIOMMU.
> > > >
> > > > struct VTDPASIDAddressSpace {
> > > > VTDBus *vtd_bus;
> > > > uint8_t devfn;
> > > > AddressSpace as;
> > > > uint32_t pasid;
> > > > IntelIOMMUState *iommu_state;
> > > > VTDContextCacheEntry context_cache_entry;
> > > > QLIST_ENTRY(VTDPASIDAddressSpace) next;
> > > > VTDPASIDCacheEntry pasid_cache_entry;
> > > > };
> > > >
> > > > Ideally, a VTDPASIDAddressSpace instance is created when a PASID is
> > > > bound with a DMA AddressSpace. Intel VT-d spec requires guest software
> > > > to issue pasid cache invalidation when bind or unbind a pasid with an
> > > > address space under caching-mode. However, as VTDPASIDAddressSpace
> > > > instances also act as pasid cache in this implementation, its creation
> > > > also happens during vIOMMU PASID tagged DMA translation. The creation
> > > > in this path will not be added in this patch since no PASID-capable
> > > > emulated devices for now.
> > > >
> > > > The implementation in this patch manages VTDPASIDAddressSpace
> > > > instances per PASID+BDF (lookup and insert will use PASID and
> > > > BDF) since Intel VT-d spec allows per-BDF PASID Table. When a guest
> > > > bind a PASID with an AddressSpace, QEMU will capture the guest pasid
> > > > selective pasid cache invalidation, and allocate remove a
> > > > VTDPASIDAddressSpace instance per the invalidation
> > > > reasons:
> > > >
> > > > *) a present pasid entry moved to non-present
> > > > *) a present pasid entry to be a present entry
> > > > *) a non-present pasid entry moved to present
> > > >
> > > > vIOMMU emulator could figure out the reason by fetching latest guest
> > > > pasid entry.
> > > >
> > > > Cc: Kevin Tian 
> > > > Cc: Jacob Pan 
> > > > Cc: Peter Xu 
> > > > Cc: Yi Sun 
> > > > Cc: Paolo Bonzini 
> > > > Cc: Richard Henderson 
> > > > Cc: Eduardo Habkost 
> > > > Signed-off-by: Liu Yi L 
> > > > ---
> > > >  hw/i386/intel_iommu.c  | 394
> > > +
> > > >  hw/i386/intel_iommu_internal.h |  14 ++
> > > >  hw/i386/trace-events   |   1 +
> > > >  include/hw/i386/intel_iommu.h  |  33 +++-
> > > >  4 files changed, 441 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index
> > > > 1daeab2..c985cae 100644
> > > > --- a/hw/i386/intel_iommu.c
> > > > +++ b/hw/i386/intel_iommu.c
> > > > @@ -40,6 +40,7 @@
> > > >  #include "kvm_i386.h"
> > > >  #include "migration/vmstate.h"
> > > >  #include "trace.h"
> > > > +#include "qemu/jhash.h"
> > > >
> > > >  /* context entry operations */
> > > >  #define VTD_CE_GET_RID2PASID(ce) \
> > > > @@ -65,6 +66,8 @@
> > > >  static void vtd_address_space_refresh_all(IntelIOMMUState *s);
> > > > static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier
> > > > *n);
> > > >
> > > > +static void vtd_pasid_cache_reset(IntelIOMMUState *s);
> > > > +
> > > >  static void vtd_panic_require_caching_mode(void)
> > > >  {
> > > >  error_report("We need to set caching-mode=on for intel-iommu to 
> > > > enable
> "
> > > > @@ -276,6 

Re: [PATCH v1 12/22] intel_iommu: add PASID cache management infrastructure

2020-03-25 Thread Peter Xu
On Wed, Mar 25, 2020 at 12:20:21PM +, Liu, Yi L wrote:
> > From: Peter Xu 
> > Sent: Wednesday, March 25, 2020 1:32 AM
> > To: Liu, Yi L 
> > Subject: Re: [PATCH v1 12/22] intel_iommu: add PASID cache management
> > infrastructure
> > 
> > On Sun, Mar 22, 2020 at 05:36:09AM -0700, Liu Yi L wrote:
> > > This patch adds a PASID cache management infrastructure based on new
> > > added structure VTDPASIDAddressSpace, which is used to track the PASID
> > > usage and future PASID tagged DMA address translation support in
> > > vIOMMU.
> > >
> > > struct VTDPASIDAddressSpace {
> > > VTDBus *vtd_bus;
> > > uint8_t devfn;
> > > AddressSpace as;
> > > uint32_t pasid;
> > > IntelIOMMUState *iommu_state;
> > > VTDContextCacheEntry context_cache_entry;
> > > QLIST_ENTRY(VTDPASIDAddressSpace) next;
> > > VTDPASIDCacheEntry pasid_cache_entry;
> > > };
> > >
> > > Ideally, a VTDPASIDAddressSpace instance is created when a PASID is
> > > bound with a DMA AddressSpace. Intel VT-d spec requires guest software
> > > to issue pasid cache invalidation when bind or unbind a pasid with an
> > > address space under caching-mode. However, as VTDPASIDAddressSpace
> > > instances also act as pasid cache in this implementation, its creation
> > > also happens during vIOMMU PASID tagged DMA translation. The creation
> > > in this path will not be added in this patch since no PASID-capable
> > > emulated devices for now.
> > >
> > > The implementation in this patch manages VTDPASIDAddressSpace
> > > instances per PASID+BDF (lookup and insert will use PASID and
> > > BDF) since Intel VT-d spec allows per-BDF PASID Table. When a guest
> > > bind a PASID with an AddressSpace, QEMU will capture the guest pasid
> > > selective pasid cache invalidation, and allocate remove a
> > > VTDPASIDAddressSpace instance per the invalidation
> > > reasons:
> > >
> > > *) a present pasid entry moved to non-present
> > > *) a present pasid entry to be a present entry
> > > *) a non-present pasid entry moved to present
> > >
> > > vIOMMU emulator could figure out the reason by fetching latest guest
> > > pasid entry.
> > >
> > > Cc: Kevin Tian 
> > > Cc: Jacob Pan 
> > > Cc: Peter Xu 
> > > Cc: Yi Sun 
> > > Cc: Paolo Bonzini 
> > > Cc: Richard Henderson 
> > > Cc: Eduardo Habkost 
> > > Signed-off-by: Liu Yi L 
> > > ---
> > >  hw/i386/intel_iommu.c  | 394
> > +
> > >  hw/i386/intel_iommu_internal.h |  14 ++
> > >  hw/i386/trace-events   |   1 +
> > >  include/hw/i386/intel_iommu.h  |  33 +++-
> > >  4 files changed, 441 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index
> > > 1daeab2..c985cae 100644
> > > --- a/hw/i386/intel_iommu.c
> > > +++ b/hw/i386/intel_iommu.c
> > > @@ -40,6 +40,7 @@
> > >  #include "kvm_i386.h"
> > >  #include "migration/vmstate.h"
> > >  #include "trace.h"
> > > +#include "qemu/jhash.h"
> > >
> > >  /* context entry operations */
> > >  #define VTD_CE_GET_RID2PASID(ce) \
> > > @@ -65,6 +66,8 @@
> > >  static void vtd_address_space_refresh_all(IntelIOMMUState *s);
> > > static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier
> > > *n);
> > >
> > > +static void vtd_pasid_cache_reset(IntelIOMMUState *s);
> > > +
> > >  static void vtd_panic_require_caching_mode(void)
> > >  {
> > >  error_report("We need to set caching-mode=on for intel-iommu to 
> > > enable "
> > > @@ -276,6 +279,7 @@ static void vtd_reset_caches(IntelIOMMUState *s)
> > >  vtd_iommu_lock(s);
> > >  vtd_reset_iotlb_locked(s);
> > >  vtd_reset_context_cache_locked(s);
> > > +vtd_pasid_cache_reset(s);
> > >  vtd_iommu_unlock(s);
> > >  }
> > >
> > > @@ -686,6 +690,11 @@ static inline bool vtd_pe_type_check(X86IOMMUState
> > *x86_iommu,
> > >  return true;
> > >  }
> > >
> > > +static inline uint16_t vtd_pe_get_domain_id(VTDPASIDEntry *pe) {
> > > +return VTD_SM_PASID_ENTRY_DID((pe)->val[1])

RE: [PATCH v1 12/22] intel_iommu: add PASID cache management infrastructure

2020-03-25 Thread Liu, Yi L
> From: Peter Xu 
> Sent: Wednesday, March 25, 2020 1:32 AM
> To: Liu, Yi L 
> Subject: Re: [PATCH v1 12/22] intel_iommu: add PASID cache management
> infrastructure
> 
> On Sun, Mar 22, 2020 at 05:36:09AM -0700, Liu Yi L wrote:
> > This patch adds a PASID cache management infrastructure based on new
> > added structure VTDPASIDAddressSpace, which is used to track the PASID
> > usage and future PASID tagged DMA address translation support in
> > vIOMMU.
> >
> > struct VTDPASIDAddressSpace {
> > VTDBus *vtd_bus;
> > uint8_t devfn;
> > AddressSpace as;
> > uint32_t pasid;
> > IntelIOMMUState *iommu_state;
> > VTDContextCacheEntry context_cache_entry;
> > QLIST_ENTRY(VTDPASIDAddressSpace) next;
> > VTDPASIDCacheEntry pasid_cache_entry;
> > };
> >
> > Ideally, a VTDPASIDAddressSpace instance is created when a PASID is
> > bound with a DMA AddressSpace. Intel VT-d spec requires guest software
> > to issue pasid cache invalidation when bind or unbind a pasid with an
> > address space under caching-mode. However, as VTDPASIDAddressSpace
> > instances also act as pasid cache in this implementation, its creation
> > also happens during vIOMMU PASID tagged DMA translation. The creation
> > in this path will not be added in this patch since no PASID-capable
> > emulated devices for now.
> >
> > The implementation in this patch manages VTDPASIDAddressSpace
> > instances per PASID+BDF (lookup and insert will use PASID and
> > BDF) since Intel VT-d spec allows per-BDF PASID Table. When a guest
> > bind a PASID with an AddressSpace, QEMU will capture the guest pasid
> > selective pasid cache invalidation, and allocate remove a
> > VTDPASIDAddressSpace instance per the invalidation
> > reasons:
> >
> > *) a present pasid entry moved to non-present
> > *) a present pasid entry to be a present entry
> > *) a non-present pasid entry moved to present
> >
> > vIOMMU emulator could figure out the reason by fetching latest guest
> > pasid entry.
> >
> > Cc: Kevin Tian 
> > Cc: Jacob Pan 
> > Cc: Peter Xu 
> > Cc: Yi Sun 
> > Cc: Paolo Bonzini 
> > Cc: Richard Henderson 
> > Cc: Eduardo Habkost 
> > Signed-off-by: Liu Yi L 
> > ---
> >  hw/i386/intel_iommu.c  | 394
> +
> >  hw/i386/intel_iommu_internal.h |  14 ++
> >  hw/i386/trace-events   |   1 +
> >  include/hw/i386/intel_iommu.h  |  33 +++-
> >  4 files changed, 441 insertions(+), 1 deletion(-)
> >
> > diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index
> > 1daeab2..c985cae 100644
> > --- a/hw/i386/intel_iommu.c
> > +++ b/hw/i386/intel_iommu.c
> > @@ -40,6 +40,7 @@
> >  #include "kvm_i386.h"
> >  #include "migration/vmstate.h"
> >  #include "trace.h"
> > +#include "qemu/jhash.h"
> >
> >  /* context entry operations */
> >  #define VTD_CE_GET_RID2PASID(ce) \
> > @@ -65,6 +66,8 @@
> >  static void vtd_address_space_refresh_all(IntelIOMMUState *s);
> > static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier
> > *n);
> >
> > +static void vtd_pasid_cache_reset(IntelIOMMUState *s);
> > +
> >  static void vtd_panic_require_caching_mode(void)
> >  {
> >  error_report("We need to set caching-mode=on for intel-iommu to enable 
> > "
> > @@ -276,6 +279,7 @@ static void vtd_reset_caches(IntelIOMMUState *s)
> >  vtd_iommu_lock(s);
> >  vtd_reset_iotlb_locked(s);
> >  vtd_reset_context_cache_locked(s);
> > +vtd_pasid_cache_reset(s);
> >  vtd_iommu_unlock(s);
> >  }
> >
> > @@ -686,6 +690,11 @@ static inline bool vtd_pe_type_check(X86IOMMUState
> *x86_iommu,
> >  return true;
> >  }
> >
> > +static inline uint16_t vtd_pe_get_domain_id(VTDPASIDEntry *pe) {
> > +return VTD_SM_PASID_ENTRY_DID((pe)->val[1]);
> > +}
> > +
> >  static inline bool vtd_pdire_present(VTDPASIDDirEntry *pdire)  {
> >  return pdire->val & 1;
> > @@ -2395,19 +2404,402 @@ static bool
> vtd_process_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
> >  return true;
> >  }
> >
> > +static inline void vtd_init_pasid_key(uint32_t pasid,
> > + uint16_t sid,
> > + struct pasid_key *key) {
> > +key->pasid = pasid;
> >

Re: [PATCH v1 12/22] intel_iommu: add PASID cache management infrastructure

2020-03-24 Thread Peter Xu
On Sun, Mar 22, 2020 at 05:36:09AM -0700, Liu Yi L wrote:
> This patch adds a PASID cache management infrastructure based on
> new added structure VTDPASIDAddressSpace, which is used to track
> the PASID usage and future PASID tagged DMA address translation
> support in vIOMMU.
> 
> struct VTDPASIDAddressSpace {
> VTDBus *vtd_bus;
> uint8_t devfn;
> AddressSpace as;
> uint32_t pasid;
> IntelIOMMUState *iommu_state;
> VTDContextCacheEntry context_cache_entry;
> QLIST_ENTRY(VTDPASIDAddressSpace) next;
> VTDPASIDCacheEntry pasid_cache_entry;
> };
> 
> Ideally, a VTDPASIDAddressSpace instance is created when a PASID
> is bound with a DMA AddressSpace. Intel VT-d spec requires guest
> software to issue pasid cache invalidation when bind or unbind a
> pasid with an address space under caching-mode. However, as
> VTDPASIDAddressSpace instances also act as pasid cache in this
> implementation, its creation also happens during vIOMMU PASID
> tagged DMA translation. The creation in this path will not be
> added in this patch since no PASID-capable emulated devices for
> now.
> 
> The implementation in this patch manages VTDPASIDAddressSpace
> instances per PASID+BDF (lookup and insert will use PASID and
> BDF) since Intel VT-d spec allows per-BDF PASID Table. When a
> guest bind a PASID with an AddressSpace, QEMU will capture the
> guest pasid selective pasid cache invalidation, and allocate
> remove a VTDPASIDAddressSpace instance per the invalidation
> reasons:
> 
> *) a present pasid entry moved to non-present
> *) a present pasid entry to be a present entry
> *) a non-present pasid entry moved to present
> 
> vIOMMU emulator could figure out the reason by fetching latest
> guest pasid entry.
> 
> Cc: Kevin Tian 
> Cc: Jacob Pan 
> Cc: Peter Xu 
> Cc: Yi Sun 
> Cc: Paolo Bonzini 
> Cc: Richard Henderson 
> Cc: Eduardo Habkost 
> Signed-off-by: Liu Yi L 
> ---
>  hw/i386/intel_iommu.c  | 394 
> +
>  hw/i386/intel_iommu_internal.h |  14 ++
>  hw/i386/trace-events   |   1 +
>  include/hw/i386/intel_iommu.h  |  33 +++-
>  4 files changed, 441 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
> index 1daeab2..c985cae 100644
> --- a/hw/i386/intel_iommu.c
> +++ b/hw/i386/intel_iommu.c
> @@ -40,6 +40,7 @@
>  #include "kvm_i386.h"
>  #include "migration/vmstate.h"
>  #include "trace.h"
> +#include "qemu/jhash.h"
>  
>  /* context entry operations */
>  #define VTD_CE_GET_RID2PASID(ce) \
> @@ -65,6 +66,8 @@
>  static void vtd_address_space_refresh_all(IntelIOMMUState *s);
>  static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n);
>  
> +static void vtd_pasid_cache_reset(IntelIOMMUState *s);
> +
>  static void vtd_panic_require_caching_mode(void)
>  {
>  error_report("We need to set caching-mode=on for intel-iommu to enable "
> @@ -276,6 +279,7 @@ static void vtd_reset_caches(IntelIOMMUState *s)
>  vtd_iommu_lock(s);
>  vtd_reset_iotlb_locked(s);
>  vtd_reset_context_cache_locked(s);
> +vtd_pasid_cache_reset(s);
>  vtd_iommu_unlock(s);
>  }
>  
> @@ -686,6 +690,11 @@ static inline bool vtd_pe_type_check(X86IOMMUState 
> *x86_iommu,
>  return true;
>  }
>  
> +static inline uint16_t vtd_pe_get_domain_id(VTDPASIDEntry *pe)
> +{
> +return VTD_SM_PASID_ENTRY_DID((pe)->val[1]);
> +}
> +
>  static inline bool vtd_pdire_present(VTDPASIDDirEntry *pdire)
>  {
>  return pdire->val & 1;
> @@ -2395,19 +2404,402 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState 
> *s, VTDInvDesc *inv_desc)
>  return true;
>  }
>  
> +static inline void vtd_init_pasid_key(uint32_t pasid,
> + uint16_t sid,
> + struct pasid_key *key)
> +{
> +key->pasid = pasid;
> +key->sid = sid;
> +}
> +
> +static guint vtd_pasid_as_key_hash(gconstpointer v)
> +{
> +struct pasid_key *key = (struct pasid_key *)v;
> +uint32_t a, b, c;
> +
> +/* Jenkins hash */
> +a = b = c = JHASH_INITVAL + sizeof(*key);
> +a += key->sid;
> +b += extract32(key->pasid, 0, 16);
> +c += extract32(key->pasid, 16, 16);
> +
> +__jhash_mix(a, b, c);
> +__jhash_final(a, b, c);
> +
> +return c;
> +}
> +
> +static gboolean vtd_pasid_as_key_equal(gconstpointer v1, gconstpointer v2)
> +{
> +const struct pasid_key *k1 = v1;
> +const struct pasid_key *k2 = v2;
> +
> +return (k1->pasid == k2->pasid) && (k1->sid == k2->sid);
> +}
> +
> +static inline int vtd_dev_get_pe_from_pasid(IntelIOMMUState *s,
> +uint8_t bus_num,
> +uint8_t devfn,
> +uint32_t pasid,
> +VTDPASIDEntry *pe)
> +{
> +VTDContextEntry ce;
> +int ret;
> +dma_addr_t pasid_dir_base;
> +

[PATCH v1 12/22] intel_iommu: add PASID cache management infrastructure

2020-03-22 Thread Liu Yi L
This patch adds a PASID cache management infrastructure based on
new added structure VTDPASIDAddressSpace, which is used to track
the PASID usage and future PASID tagged DMA address translation
support in vIOMMU.

struct VTDPASIDAddressSpace {
VTDBus *vtd_bus;
uint8_t devfn;
AddressSpace as;
uint32_t pasid;
IntelIOMMUState *iommu_state;
VTDContextCacheEntry context_cache_entry;
QLIST_ENTRY(VTDPASIDAddressSpace) next;
VTDPASIDCacheEntry pasid_cache_entry;
};

Ideally, a VTDPASIDAddressSpace instance is created when a PASID
is bound with a DMA AddressSpace. Intel VT-d spec requires guest
software to issue pasid cache invalidation when bind or unbind a
pasid with an address space under caching-mode. However, as
VTDPASIDAddressSpace instances also act as pasid cache in this
implementation, its creation also happens during vIOMMU PASID
tagged DMA translation. The creation in this path will not be
added in this patch since no PASID-capable emulated devices for
now.

The implementation in this patch manages VTDPASIDAddressSpace
instances per PASID+BDF (lookup and insert will use PASID and
BDF) since Intel VT-d spec allows per-BDF PASID Table. When a
guest bind a PASID with an AddressSpace, QEMU will capture the
guest pasid selective pasid cache invalidation, and allocate
remove a VTDPASIDAddressSpace instance per the invalidation
reasons:

*) a present pasid entry moved to non-present
*) a present pasid entry to be a present entry
*) a non-present pasid entry moved to present

vIOMMU emulator could figure out the reason by fetching latest
guest pasid entry.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Yi Sun 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Signed-off-by: Liu Yi L 
---
 hw/i386/intel_iommu.c  | 394 +
 hw/i386/intel_iommu_internal.h |  14 ++
 hw/i386/trace-events   |   1 +
 include/hw/i386/intel_iommu.h  |  33 +++-
 4 files changed, 441 insertions(+), 1 deletion(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 1daeab2..c985cae 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -40,6 +40,7 @@
 #include "kvm_i386.h"
 #include "migration/vmstate.h"
 #include "trace.h"
+#include "qemu/jhash.h"
 
 /* context entry operations */
 #define VTD_CE_GET_RID2PASID(ce) \
@@ -65,6 +66,8 @@
 static void vtd_address_space_refresh_all(IntelIOMMUState *s);
 static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n);
 
+static void vtd_pasid_cache_reset(IntelIOMMUState *s);
+
 static void vtd_panic_require_caching_mode(void)
 {
 error_report("We need to set caching-mode=on for intel-iommu to enable "
@@ -276,6 +279,7 @@ static void vtd_reset_caches(IntelIOMMUState *s)
 vtd_iommu_lock(s);
 vtd_reset_iotlb_locked(s);
 vtd_reset_context_cache_locked(s);
+vtd_pasid_cache_reset(s);
 vtd_iommu_unlock(s);
 }
 
@@ -686,6 +690,11 @@ static inline bool vtd_pe_type_check(X86IOMMUState 
*x86_iommu,
 return true;
 }
 
+static inline uint16_t vtd_pe_get_domain_id(VTDPASIDEntry *pe)
+{
+return VTD_SM_PASID_ENTRY_DID((pe)->val[1]);
+}
+
 static inline bool vtd_pdire_present(VTDPASIDDirEntry *pdire)
 {
 return pdire->val & 1;
@@ -2395,19 +2404,402 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, 
VTDInvDesc *inv_desc)
 return true;
 }
 
+static inline void vtd_init_pasid_key(uint32_t pasid,
+ uint16_t sid,
+ struct pasid_key *key)
+{
+key->pasid = pasid;
+key->sid = sid;
+}
+
+static guint vtd_pasid_as_key_hash(gconstpointer v)
+{
+struct pasid_key *key = (struct pasid_key *)v;
+uint32_t a, b, c;
+
+/* Jenkins hash */
+a = b = c = JHASH_INITVAL + sizeof(*key);
+a += key->sid;
+b += extract32(key->pasid, 0, 16);
+c += extract32(key->pasid, 16, 16);
+
+__jhash_mix(a, b, c);
+__jhash_final(a, b, c);
+
+return c;
+}
+
+static gboolean vtd_pasid_as_key_equal(gconstpointer v1, gconstpointer v2)
+{
+const struct pasid_key *k1 = v1;
+const struct pasid_key *k2 = v2;
+
+return (k1->pasid == k2->pasid) && (k1->sid == k2->sid);
+}
+
+static inline int vtd_dev_get_pe_from_pasid(IntelIOMMUState *s,
+uint8_t bus_num,
+uint8_t devfn,
+uint32_t pasid,
+VTDPASIDEntry *pe)
+{
+VTDContextEntry ce;
+int ret;
+dma_addr_t pasid_dir_base;
+
+if (!s->root_scalable) {
+return -VTD_FR_PASID_TABLE_INV;
+}
+
+ret = vtd_dev_to_context_entry(s, bus_num, devfn, );
+if (ret) {
+return ret;
+}
+
+pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE();
+ret = vtd_get_pe_from_pasid_table(s,
+  pasid_dir_base, pasid, pe);
+
+