[PATCH 1/2] VT-d: Support multiple device assignment for KVM

Han, Weidong weidong.han at intel.com
Wed Nov 26 06:04:52 PST 2008


Avi Kivity wrote:
> Han, Weidong wrote:
>> In order to support multiple device assignment for KVM, this patch
>> does following main changes: 
>>    - extend dmar_domain to own multiple devices from different
>> iommus, use a bitmap of iommus to replace iommu pointer in
>> dmar_domain.  
>>    - add a flag DOMAIN_FLAG_VIRTUAL_MACHINE to represent KVM VT-d
>> usage. Many functions (e.g. intel_map_single() and
>> intel_unmap_single()) won't be used by KVM VT-d. Let them return
>> directly when this flag is set.   
>> 
> 
> 
> This seems brittle.  An API that has some functions shorted out
> depending on some flag is hard to understand and use.

This flag just helps identify kvm VT-d usage, and let kvm VT-d APIs reuse native VT-d code, it needn't duplicate code for kvm VT-d APIs, and it won't impact existed native VT-d code. 

> 
> We should either implement the functions, or split the API into a
> basic version that talks only to one device, and an expanded versions
> that talks to multiple devices, and is implemented by the using the
> lower level API.  This may require more changes due to the need to
> share io pagetables.

The expanded versions that supports multiple devices will need to change dmar_domain, this will cause lots of changes, almost duplicate the main functions.

> 
>>    - "SAGAW" capability may be different across iommus, that's to
>> say the VT-d page table levels may be different among iommus. This
>> patch uses a defaut agaw, and skip top levels of page tables for
>> iommus which have smaller agaw than default.   
>> 
> 
> Neat trick.
> 
>>  void free_dmar_iommu(struct intel_iommu *iommu)
>>  {
>>         struct dmar_domain *domain;
>> @@ -960,7 +1054,14 @@ void free_dmar_iommu(struct intel_iommu *iommu)
>>         for (; i < cap_ndoms(iommu->cap); ) {
>>                 domain = iommu->domains[i];
>>                 clear_bit(i, iommu->domain_ids);
>> -               domain_exit(domain);
>> +
>> +               if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) {
>> +                       /* domain may be referenced by other iommus
>> */ +                       if (domain_in_other_iommus(domain, iommu)
>> == 0) +                               domain_exit(domain); +        
>> } +               else
>> +                       domain_exit(domain);
>> 
> 
> Things like this are best expressed using reference counts, which
> removes the need for the test as well.

will add a reference count for it.

> 
>> +
>> +               /* Skip top levels of page tables for
>> +                * iommu which has less agaw than default. +        
>> */ +               for (agaw = domain->agaw; agaw != iommu->agaw;
>> agaw--) { +                       pgd =
>> phys_to_virt(dma_pte_addr(*pgd)); +                       if
>> (!dma_pte_present(*pgd)) { +                              
>> spin_unlock_irqrestore(&iommu->lock, flags); +                      
>> return -ENOMEM; +                       }
>> +               }
>> +       }
>> 
> 
> Need to check that the agaw is sufficient for mapped memory (and when
> adding a device or mapping more memory, need a similar check).

I think we can check the smallest agaw across iommus for mapped memory when mapping memory.

Regards,
Weidong



More information about the iommu mailing list