[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 6 of 6] amd iommu: enable ats devices



>>> On 25.10.11 at 15:07, Wei Wang <wei.wang2@xxxxxxx> wrote:
> # HG changeset patch
> # User Wei Wang <wei.wang2@xxxxxxx>
> # Date 1319472702 -7200
> # Node ID b84967db0efb875bca4d95f47fc77b46cd065665
> # Parent  8ec947b278afaf89acadf905237c95ba7b64524a
> amd iommu: enable ats devices
> 
> Signed-off-by: Wei Wang <wei.wang2@xxxxxxx 
> 
> diff -r 8ec947b278af -r b84967db0efb xen/drivers/passthrough/amd/iommu_map.c
> --- a/xen/drivers/passthrough/amd/iommu_map.c Mon Oct 24 18:11:40 2011 +0200
> +++ b/xen/drivers/passthrough/amd/iommu_map.c Mon Oct 24 18:11:42 2011 +0200
> @@ -369,6 +369,17 @@ void amd_iommu_set_root_page_table(
>      dte[0] = entry;
>  }
>  
> +void iommu_dte_set_iotlb(u32 *dte, u8 i)
> +{
> +    u32 entry;
> +
> +    entry = dte[3];
> +    set_field_in_reg_u32(!!i, entry,
> +                         IOMMU_DEV_TABLE_IOTLB_SUPPORT_MASK,
> +                         IOMMU_DEV_TABLE_IOTLB_SUPPORT_SHIFT, &entry);
> +    dte[3] = entry;
> +}
> +
>  void __init amd_iommu_set_intremap_table(
>      u32 *dte, u64 intremap_ptr, u8 int_valid)
>  {
> diff -r 8ec947b278af -r b84967db0efb 
> xen/drivers/passthrough/amd/pci_amd_iommu.c
> --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c     Mon Oct 24 18:11:40 
> 2011 +0200
> +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c     Mon Oct 24 18:11:42 
> 2011 
> +0200
> @@ -25,6 +25,7 @@
>  #include <asm/hvm/iommu.h>
>  #include <asm/amd-iommu.h>
>  #include <asm/hvm/svm/amd-iommu-proto.h>
> +#include "../x86/ats.h"
>  
>  struct amd_iommu *find_iommu_for_device(int seg, int bdf)
>  {
> @@ -81,11 +82,12 @@ static void disable_translation(u32 *dte
>  }
>  
>  static void amd_iommu_setup_domain_device(
> -    struct domain *domain, struct amd_iommu *iommu, int bdf)
> +    struct domain *domain, struct amd_iommu *iommu, u8 bus, u8 devfn)
>  {
>      void *dte;
>      unsigned long flags;
>      int req_id, valid = 1;
> +    int dte_i = 0;
>  
>      struct hvm_iommu *hd = domain_hvm_iommu(domain);
>  
> @@ -94,8 +96,11 @@ static void amd_iommu_setup_domain_devic
>      if ( iommu_passthrough && (domain->domain_id == 0) )
>          valid = 0;
>  
> +    if ( ats_enabled )
> +        dte_i = 1;
> +
>      /* get device-table entry */
> -    req_id = get_dma_requestor_id(iommu->seg, bdf);
> +    req_id = get_dma_requestor_id(iommu->seg, (bus << 8) | devfn);
>      dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
>  
>      spin_lock_irqsave(&iommu->lock, flags);
> @@ -107,6 +112,9 @@ static void amd_iommu_setup_domain_devic
>              (u32 *)dte, page_to_maddr(hd->root_table), hd->domain_id,
>              hd->paging_mode, valid);
>  
> +        if ( pci_ats_device(iommu->seg, bus, devfn) && iommu->iotlb_support )
> +            iommu_dte_set_iotlb((u32 *)dte, dte_i);
> +
>          invalidate_dev_table_entry(iommu, req_id);
>          flush_command_buffer(iommu);
>  
> @@ -118,6 +126,21 @@ static void amd_iommu_setup_domain_devic
>      }
>  
>      spin_unlock_irqrestore(&iommu->lock, flags);
> +
> +    ASSERT(spin_is_locked(&pcidevs_lock));
> +
> +    if ( pci_ats_device(iommu->seg, bus, devfn) && ats_enabled &&

Iirc pci_ats_device() returning non-zero already implies ats_enabled.

> +         !pci_ats_enabled(iommu->seg, bus, devfn) )
> +    {
> +        struct pci_dev* pdev;

Formatting (need a newline here, plus asterisk and space again should
switch places).

> +        enable_ats_device(iommu->seg, bus, devfn);
> +
> +        ASSERT(spin_is_locked(&pcidevs_lock));
> +        pdev = pci_get_pdev(iommu->seg, bus, devfn);
> +
> +        if ( pdev )

Is it actually possible/valid for pdev to be NULL here? If not, you'd
want ASSERT()/BUG_ON() instead of if() here.

> +            amd_iommu_flush_iotlb(pdev, INV_IOMMU_ALL_PAGES_ADDRESS, 0);
> +    }
>  }
>  
>  static void __init amd_iommu_setup_dom0_device(struct pci_dev *pdev)
> @@ -126,7 +149,8 @@ static void __init amd_iommu_setup_dom0_
>      struct amd_iommu *iommu = find_iommu_for_device(pdev->seg, bdf);
>  
>      if ( likely(iommu != NULL) )
> -        amd_iommu_setup_domain_device(pdev->domain, iommu, bdf);
> +        amd_iommu_setup_domain_device(pdev->domain, iommu, pdev->bus, 
> +                                      pdev->devfn);
>      else
>          AMD_IOMMU_DEBUG("No iommu for device %04x:%02x:%02x.%u\n",
>                          pdev->seg, pdev->bus,
> @@ -261,21 +285,26 @@ static void __init amd_iommu_dom0_init(s
>      setup_dom0_pci_devices(d, amd_iommu_setup_dom0_device);
>  }
>  
> -static void amd_iommu_disable_domain_device(
> -    struct domain *domain, struct amd_iommu *iommu, int bdf)
> +void amd_iommu_disable_domain_device(struct domain *domain, 
> +                                     struct amd_iommu *iommu, u8 bus, u8 
> devfn)

If you really want to do this, then ...

>  {
>      void *dte;
>      unsigned long flags;
>      int req_id;
>  
>      BUG_ON ( iommu->dev_table.buffer == NULL );
> -    req_id = get_dma_requestor_id(iommu->seg, bdf);
> +
> +    req_id = get_dma_requestor_id(iommu->seg, (bus << 8) | devfn);

... you want to use PCI_BDF2() here.

>      dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
>  
>      spin_lock_irqsave(&iommu->lock, flags);
>      if ( is_translation_valid((u32 *)dte) )
>      {
>          disable_translation((u32 *)dte);
> +
> +        if ( pci_ats_device(iommu->seg, bus, devfn) && iommu->iotlb_support )
> +            iommu_dte_set_iotlb((u32 *)dte, 0);
> +
>          invalidate_dev_table_entry(iommu, req_id);
>          flush_command_buffer(iommu);
>          AMD_IOMMU_DEBUG("Disable: device id = 0x%04x, "
> @@ -284,6 +313,12 @@ static void amd_iommu_disable_domain_dev
>                          domain_hvm_iommu(domain)->paging_mode);
>      }
>      spin_unlock_irqrestore(&iommu->lock, flags);
> +
> +    ASSERT(spin_is_locked(&pcidevs_lock));
> +
> +    if ( pci_ats_device(iommu->seg, bus, devfn) && ats_enabled && 

See above.

> +         pci_ats_enabled(iommu->seg, bus, devfn) )
> +       disable_ats_device(iommu->seg, bus, devfn); 
>  }
>  
>  static int reassign_device( struct domain *source, struct domain *target,
> @@ -310,7 +345,7 @@ static int reassign_device( struct domai
>          return -ENODEV;
>      }
>  
> -    amd_iommu_disable_domain_device(source, iommu, bdf);
> +    amd_iommu_disable_domain_device(source, iommu, bus, devfn);
>  
>      list_move(&pdev->domain_list, &target->arch.pdev_list);
>      pdev->domain = target;
> @@ -320,7 +355,7 @@ static int reassign_device( struct domai
>      if ( t->root_table == NULL )
>          allocate_domain_resources(t);
>  
> -    amd_iommu_setup_domain_device(target, iommu, bdf);
> +    amd_iommu_setup_domain_device(target, iommu, bus, devfn);
>      AMD_IOMMU_DEBUG("Re-assign %04x:%02x:%02x.%u from dom%d to dom%d\n",
>                      seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
>                      source->domain_id, target->domain_id);
> @@ -432,7 +467,8 @@ static int amd_iommu_add_device(struct p
>          return -ENODEV;
>      }
>  
> -    amd_iommu_setup_domain_device(pdev->domain, iommu, bdf);
> +    amd_iommu_setup_domain_device(pdev->domain, iommu, 
> +                                  pdev->bus, pdev->devfn);
>      return 0;
>  }
>  
> @@ -454,7 +490,8 @@ static int amd_iommu_remove_device(struc
>          return -ENODEV;
>      }
>  
> -    amd_iommu_disable_domain_device(pdev->domain, iommu, bdf);
> +    amd_iommu_disable_domain_device(pdev->domain, iommu, 
> +                                    pdev->bus, pdev->devfn);
>      return 0;
>  }
>  
> diff -r 8ec947b278af -r b84967db0efb 
> xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
> --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h   Mon Oct 24 18:11:40 
> 2011 +0200
> +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h   Mon Oct 24 18:11:42 
> 2011 
> +0200
> @@ -75,6 +75,7 @@ void amd_iommu_set_intremap_table(
>      u32 *dte, u64 intremap_ptr, u8 int_valid);
>  void amd_iommu_set_root_page_table(
>      u32 *dte, u64 root_ptr, u16 domain_id, u8 paging_mode, u8 valid);
> +void iommu_dte_set_iotlb(u32 *dte, u8 i);
>  void invalidate_dev_table_entry(struct amd_iommu *iommu, u16 devic_id);
>  
>  /* send cmd to iommu */


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.