All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] VT-d: don't crash when PTE bits 52 and up are non-zero
@ 2014-12-19 11:26 Jan Beulich
  2014-12-23  6:52 ` Tian, Kevin
  0 siblings, 1 reply; 6+ messages in thread
From: Jan Beulich @ 2014-12-19 11:26 UTC (permalink / raw)
  To: xen-devel; +Cc: Yang Z Zhang, Kevin Tian

[-- Attachment #1: Type: text/plain, Size: 4339 bytes --]

This can (and will) be legitimately the case when sharing page tables
with EPT (more of a problem before p2m_access_rwx became zero, but
still possible even now when other than that is the default for a
guest), leading to an unconditional crash (in print_vtd_entries())
when a DMA remapping fault occurs.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
Regarding the release, if the changes to iommu.c are deemed too
extensive, then _I think_ they could be split off (that code ought to
come into play only when not sharing page tables between VT-d and EPT,
and VT-d code never sets the offending bits to non-zero values afaict).

--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -258,8 +258,7 @@ static u64 addr_to_dma_page_maddr(struct
     struct dma_pte *parent, *pte = NULL;
     int level = agaw_to_level(hd->arch.agaw);
     int offset;
-    u64 pte_maddr = 0, maddr;
-    u64 *vaddr = NULL;
+    u64 pte_maddr = 0;
 
     addr &= (((u64)1) << addr_width) - 1;
     ASSERT(spin_is_locked(&hd->arch.mapping_lock));
@@ -281,19 +280,19 @@ static u64 addr_to_dma_page_maddr(struct
         offset = address_level_offset(addr, level);
         pte = &parent[offset];
 
-        if ( dma_pte_addr(*pte) == 0 )
+        pte_maddr = dma_pte_addr(*pte);
+        if ( !pte_maddr )
         {
             if ( !alloc )
                 break;
 
             pdev = pci_get_pdev_by_domain(domain, -1, -1, -1);
             drhd = acpi_find_matched_drhd_unit(pdev);
-            maddr = alloc_pgtable_maddr(drhd, 1);
-            if ( !maddr )
+            pte_maddr = alloc_pgtable_maddr(drhd, 1);
+            if ( !pte_maddr )
                 break;
 
-            dma_set_pte_addr(*pte, maddr);
-            vaddr = map_vtd_domain_page(maddr);
+            dma_set_pte_addr(*pte, pte_maddr);
 
             /*
              * high level table always sets r/w, last level
@@ -303,21 +302,12 @@ static u64 addr_to_dma_page_maddr(struct
             dma_set_pte_writable(*pte);
             iommu_flush_cache_entry(pte, sizeof(struct dma_pte));
         }
-        else
-        {
-            vaddr = map_vtd_domain_page(pte->val);
-        }
 
         if ( level == 2 )
-        {
-            pte_maddr = pte->val & PAGE_MASK_4K;
-            unmap_vtd_domain_page(vaddr);
             break;
-        }
 
         unmap_vtd_domain_page(parent);
-        parent = (struct dma_pte *)vaddr;
-        vaddr = NULL;
+        parent = map_vtd_domain_page(pte_maddr);
         level--;
     }
 
@@ -2449,7 +2439,7 @@ static void vtd_dump_p2m_table_level(pad
             printk("%*sgfn: %08lx mfn: %08lx\n",
                    indent, "",
                    (unsigned long)(address >> PAGE_SHIFT_4K),
-                   (unsigned long)(pte->val >> PAGE_SHIFT_4K));
+                   (unsigned long)(dma_pte_addr(*pte) >> PAGE_SHIFT_4K));
     }
 
     unmap_vtd_domain_page(pt_vaddr);
--- a/xen/drivers/passthrough/vtd/iommu.h
+++ b/xen/drivers/passthrough/vtd/iommu.h
@@ -276,7 +276,7 @@ struct dma_pte {
 #define dma_set_pte_snp(p)  do {(p).val |= DMA_PTE_SNP;} while(0)
 #define dma_set_pte_prot(p, prot) \
             do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0)
-#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K)
+#define dma_pte_addr(p) ((p).val & PADDR_MASK & PAGE_MASK_4K)
 #define dma_set_pte_addr(p, addr) do {\
             (p).val |= ((addr) & PAGE_MASK_4K); } while (0)
 #define dma_pte_present(p) (((p).val & 3) != 0)
--- a/xen/drivers/passthrough/vtd/utils.c
+++ b/xen/drivers/passthrough/vtd/utils.c
@@ -170,16 +170,16 @@ void print_vtd_entries(struct iommu *iom
         l_index = get_level_index(gmfn, level);
         printk("    l%d_index = %x\n", level, l_index);
 
-        pte.val = val = l[l_index];
+        pte.val = l[l_index];
         unmap_vtd_domain_page(l);
-        printk("    l%d[%x] = %"PRIx64"\n", level, l_index, val);
+        printk("    l%d[%x] = %"PRIx64"\n", level, l_index, pte.val);
 
-        pte.val = val;
         if ( !dma_pte_present(pte) )
         {
             printk("    l%d[%x] not present\n", level, l_index);
             break;
         }
+        val = dma_pte_addr(pte);
     } while ( --level );
 }
 



[-- Attachment #2: VT-d-mask-maddr.patch --]
[-- Type: text/plain, Size: 4393 bytes --]

VT-d: don't crash when PTE bits 52 and up are non-zero

This can (and will) be legitimately the case when sharing page tables
with EPT (more of a problem before p2m_access_rwx became zero, but
still possible even now when other than that is the default for a
guest), leading to an unconditional crash (in print_vtd_entries())
when a DMA remapping fault occurs.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
Regarding the release, if the changes to iommu.c are deemed too
extensive, then _I think_ they could be split off (that code ought to
come into play only when not sharing page tables between VT-d and EPT,
and VT-d code never sets the offending bits to non-zero values afaict).

--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -258,8 +258,7 @@ static u64 addr_to_dma_page_maddr(struct
     struct dma_pte *parent, *pte = NULL;
     int level = agaw_to_level(hd->arch.agaw);
     int offset;
-    u64 pte_maddr = 0, maddr;
-    u64 *vaddr = NULL;
+    u64 pte_maddr = 0;
 
     addr &= (((u64)1) << addr_width) - 1;
     ASSERT(spin_is_locked(&hd->arch.mapping_lock));
@@ -281,19 +280,19 @@ static u64 addr_to_dma_page_maddr(struct
         offset = address_level_offset(addr, level);
         pte = &parent[offset];
 
-        if ( dma_pte_addr(*pte) == 0 )
+        pte_maddr = dma_pte_addr(*pte);
+        if ( !pte_maddr )
         {
             if ( !alloc )
                 break;
 
             pdev = pci_get_pdev_by_domain(domain, -1, -1, -1);
             drhd = acpi_find_matched_drhd_unit(pdev);
-            maddr = alloc_pgtable_maddr(drhd, 1);
-            if ( !maddr )
+            pte_maddr = alloc_pgtable_maddr(drhd, 1);
+            if ( !pte_maddr )
                 break;
 
-            dma_set_pte_addr(*pte, maddr);
-            vaddr = map_vtd_domain_page(maddr);
+            dma_set_pte_addr(*pte, pte_maddr);
 
             /*
              * high level table always sets r/w, last level
@@ -303,21 +302,12 @@ static u64 addr_to_dma_page_maddr(struct
             dma_set_pte_writable(*pte);
             iommu_flush_cache_entry(pte, sizeof(struct dma_pte));
         }
-        else
-        {
-            vaddr = map_vtd_domain_page(pte->val);
-        }
 
         if ( level == 2 )
-        {
-            pte_maddr = pte->val & PAGE_MASK_4K;
-            unmap_vtd_domain_page(vaddr);
             break;
-        }
 
         unmap_vtd_domain_page(parent);
-        parent = (struct dma_pte *)vaddr;
-        vaddr = NULL;
+        parent = map_vtd_domain_page(pte_maddr);
         level--;
     }
 
@@ -2449,7 +2439,7 @@ static void vtd_dump_p2m_table_level(pad
             printk("%*sgfn: %08lx mfn: %08lx\n",
                    indent, "",
                    (unsigned long)(address >> PAGE_SHIFT_4K),
-                   (unsigned long)(pte->val >> PAGE_SHIFT_4K));
+                   (unsigned long)(dma_pte_addr(*pte) >> PAGE_SHIFT_4K));
     }
 
     unmap_vtd_domain_page(pt_vaddr);
--- a/xen/drivers/passthrough/vtd/iommu.h
+++ b/xen/drivers/passthrough/vtd/iommu.h
@@ -276,7 +276,7 @@ struct dma_pte {
 #define dma_set_pte_snp(p)  do {(p).val |= DMA_PTE_SNP;} while(0)
 #define dma_set_pte_prot(p, prot) \
             do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0)
-#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K)
+#define dma_pte_addr(p) ((p).val & PADDR_MASK & PAGE_MASK_4K)
 #define dma_set_pte_addr(p, addr) do {\
             (p).val |= ((addr) & PAGE_MASK_4K); } while (0)
 #define dma_pte_present(p) (((p).val & 3) != 0)
--- a/xen/drivers/passthrough/vtd/utils.c
+++ b/xen/drivers/passthrough/vtd/utils.c
@@ -170,16 +170,16 @@ void print_vtd_entries(struct iommu *iom
         l_index = get_level_index(gmfn, level);
         printk("    l%d_index = %x\n", level, l_index);
 
-        pte.val = val = l[l_index];
+        pte.val = l[l_index];
         unmap_vtd_domain_page(l);
-        printk("    l%d[%x] = %"PRIx64"\n", level, l_index, val);
+        printk("    l%d[%x] = %"PRIx64"\n", level, l_index, pte.val);
 
-        pte.val = val;
         if ( !dma_pte_present(pte) )
         {
             printk("    l%d[%x] not present\n", level, l_index);
             break;
         }
+        val = dma_pte_addr(pte);
     } while ( --level );
 }
 

[-- Attachment #3: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] VT-d: don't crash when PTE bits 52 and up are non-zero
  2014-12-19 11:26 [PATCH] VT-d: don't crash when PTE bits 52 and up are non-zero Jan Beulich
@ 2014-12-23  6:52 ` Tian, Kevin
  2014-12-23 14:27   ` Jan Beulich
  2015-01-07 10:15   ` Jan Beulich
  0 siblings, 2 replies; 6+ messages in thread
From: Tian, Kevin @ 2014-12-23  6:52 UTC (permalink / raw)
  To: Jan Beulich, xen-devel; +Cc: Zhang, Yang Z

> From: Jan Beulich [mailto:JBeulich@suse.com]
> Sent: Friday, December 19, 2014 7:26 PM
> 
> This can (and will) be legitimately the case when sharing page tables
> with EPT (more of a problem before p2m_access_rwx became zero, but
> still possible even now when other than that is the default for a
> guest), leading to an unconditional crash (in print_vtd_entries())
> when a DMA remapping fault occurs.

could you elaborate the scenarios when bits 52+ are non-zero?

> 
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

but the changes looks reasonable to me.

Signed-off-by: Kevin Tian <kevin.tian@intel.com>

> ---
> Regarding the release, if the changes to iommu.c are deemed too
> extensive, then _I think_ they could be split off (that code ought to
> come into play only when not sharing page tables between VT-d and EPT,
> and VT-d code never sets the offending bits to non-zero values afaict).
> 
> --- a/xen/drivers/passthrough/vtd/iommu.c
> +++ b/xen/drivers/passthrough/vtd/iommu.c
> @@ -258,8 +258,7 @@ static u64 addr_to_dma_page_maddr(struct
>      struct dma_pte *parent, *pte = NULL;
>      int level = agaw_to_level(hd->arch.agaw);
>      int offset;
> -    u64 pte_maddr = 0, maddr;
> -    u64 *vaddr = NULL;
> +    u64 pte_maddr = 0;
> 
>      addr &= (((u64)1) << addr_width) - 1;
>      ASSERT(spin_is_locked(&hd->arch.mapping_lock));
> @@ -281,19 +280,19 @@ static u64 addr_to_dma_page_maddr(struct
>          offset = address_level_offset(addr, level);
>          pte = &parent[offset];
> 
> -        if ( dma_pte_addr(*pte) == 0 )
> +        pte_maddr = dma_pte_addr(*pte);
> +        if ( !pte_maddr )
>          {
>              if ( !alloc )
>                  break;
> 
>              pdev = pci_get_pdev_by_domain(domain, -1, -1, -1);
>              drhd = acpi_find_matched_drhd_unit(pdev);
> -            maddr = alloc_pgtable_maddr(drhd, 1);
> -            if ( !maddr )
> +            pte_maddr = alloc_pgtable_maddr(drhd, 1);
> +            if ( !pte_maddr )
>                  break;
> 
> -            dma_set_pte_addr(*pte, maddr);
> -            vaddr = map_vtd_domain_page(maddr);
> +            dma_set_pte_addr(*pte, pte_maddr);
> 
>              /*
>               * high level table always sets r/w, last level
> @@ -303,21 +302,12 @@ static u64 addr_to_dma_page_maddr(struct
>              dma_set_pte_writable(*pte);
>              iommu_flush_cache_entry(pte, sizeof(struct dma_pte));
>          }
> -        else
> -        {
> -            vaddr = map_vtd_domain_page(pte->val);
> -        }
> 
>          if ( level == 2 )
> -        {
> -            pte_maddr = pte->val & PAGE_MASK_4K;
> -            unmap_vtd_domain_page(vaddr);
>              break;
> -        }
> 
>          unmap_vtd_domain_page(parent);
> -        parent = (struct dma_pte *)vaddr;
> -        vaddr = NULL;
> +        parent = map_vtd_domain_page(pte_maddr);
>          level--;
>      }
> 
> @@ -2449,7 +2439,7 @@ static void vtd_dump_p2m_table_level(pad
>              printk("%*sgfn: %08lx mfn: %08lx\n",
>                     indent, "",
>                     (unsigned long)(address >> PAGE_SHIFT_4K),
> -                   (unsigned long)(pte->val >> PAGE_SHIFT_4K));
> +                   (unsigned long)(dma_pte_addr(*pte) >>
> PAGE_SHIFT_4K));
>      }
> 
>      unmap_vtd_domain_page(pt_vaddr);
> --- a/xen/drivers/passthrough/vtd/iommu.h
> +++ b/xen/drivers/passthrough/vtd/iommu.h
> @@ -276,7 +276,7 @@ struct dma_pte {
>  #define dma_set_pte_snp(p)  do {(p).val |= DMA_PTE_SNP;} while(0)
>  #define dma_set_pte_prot(p, prot) \
>              do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0)
> -#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K)
> +#define dma_pte_addr(p) ((p).val & PADDR_MASK & PAGE_MASK_4K)
>  #define dma_set_pte_addr(p, addr) do {\
>              (p).val |= ((addr) & PAGE_MASK_4K); } while (0)
>  #define dma_pte_present(p) (((p).val & 3) != 0)
> --- a/xen/drivers/passthrough/vtd/utils.c
> +++ b/xen/drivers/passthrough/vtd/utils.c
> @@ -170,16 +170,16 @@ void print_vtd_entries(struct iommu *iom
>          l_index = get_level_index(gmfn, level);
>          printk("    l%d_index = %x\n", level, l_index);
> 
> -        pte.val = val = l[l_index];
> +        pte.val = l[l_index];
>          unmap_vtd_domain_page(l);
> -        printk("    l%d[%x] = %"PRIx64"\n", level, l_index, val);
> +        printk("    l%d[%x] = %"PRIx64"\n", level, l_index, pte.val);
> 
> -        pte.val = val;
>          if ( !dma_pte_present(pte) )
>          {
>              printk("    l%d[%x] not present\n", level, l_index);
>              break;
>          }
> +        val = dma_pte_addr(pte);
>      } while ( --level );
>  }
> 
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] VT-d: don't crash when PTE bits 52 and up are non-zero
  2014-12-23  6:52 ` Tian, Kevin
@ 2014-12-23 14:27   ` Jan Beulich
  2015-01-07 10:15   ` Jan Beulich
  1 sibling, 0 replies; 6+ messages in thread
From: Jan Beulich @ 2014-12-23 14:27 UTC (permalink / raw)
  To: Kevin Tian; +Cc: Yang Z Zhang, xen-devel

>>> On 23.12.14 at 07:52, <kevin.tian@intel.com> wrote:
>>  From: Jan Beulich [mailto:JBeulich@suse.com]
>> Sent: Friday, December 19, 2014 7:26 PM
>> 
>> This can (and will) be legitimately the case when sharing page tables
>> with EPT (more of a problem before p2m_access_rwx became zero, but
>> still possible even now when other than that is the default for a
>> guest), leading to an unconditional crash (in print_vtd_entries())
>> when a DMA remapping fault occurs.
> 
> could you elaborate the scenarios when bits 52+ are non-zero?

This happens with shared page tables and a non-zero access type.

Jan

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] VT-d: don't crash when PTE bits 52 and up are non-zero
  2014-12-23  6:52 ` Tian, Kevin
  2014-12-23 14:27   ` Jan Beulich
@ 2015-01-07 10:15   ` Jan Beulich
  2015-01-07 15:00     ` Konrad Rzeszutek Wilk
  2015-01-08  0:41     ` Tian, Kevin
  1 sibling, 2 replies; 6+ messages in thread
From: Jan Beulich @ 2015-01-07 10:15 UTC (permalink / raw)
  To: Kevin Tian, Konrad Rzeszutek Wilk; +Cc: Yang Z Zhang, xen-devel

>>> On 23.12.14 at 07:52, <kevin.tian@intel.com> wrote:
>>  From: Jan Beulich [mailto:JBeulich@suse.com]
>> Sent: Friday, December 19, 2014 7:26 PM
>> 
>> This can (and will) be legitimately the case when sharing page tables
>> with EPT (more of a problem before p2m_access_rwx became zero, but
>> still possible even now when other than that is the default for a
>> guest), leading to an unconditional crash (in print_vtd_entries())
>> when a DMA remapping fault occurs.
> 
> could you elaborate the scenarios when bits 52+ are non-zero?
> 
>> 
>> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> 
> but the changes looks reasonable to me.
> 
> Signed-off-by: Kevin Tian <kevin.tian@intel.com>

I translated this to a Reviewed-by, as S-o-b doesn't seem to make
sense here.

Konrad - please indicate whether this can also go into 4.5.

Jan

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] VT-d: don't crash when PTE bits 52 and up are non-zero
  2015-01-07 10:15   ` Jan Beulich
@ 2015-01-07 15:00     ` Konrad Rzeszutek Wilk
  2015-01-08  0:41     ` Tian, Kevin
  1 sibling, 0 replies; 6+ messages in thread
From: Konrad Rzeszutek Wilk @ 2015-01-07 15:00 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Yang Z Zhang, xen-devel, Kevin Tian

On Wed, Jan 07, 2015 at 10:15:39AM +0000, Jan Beulich wrote:
> >>> On 23.12.14 at 07:52, <kevin.tian@intel.com> wrote:
> >>  From: Jan Beulich [mailto:JBeulich@suse.com]
> >> Sent: Friday, December 19, 2014 7:26 PM
> >> 
> >> This can (and will) be legitimately the case when sharing page tables
> >> with EPT (more of a problem before p2m_access_rwx became zero, but
> >> still possible even now when other than that is the default for a
> >> guest), leading to an unconditional crash (in print_vtd_entries())
> >> when a DMA remapping fault occurs.
> > 
> > could you elaborate the scenarios when bits 52+ are non-zero?
> > 
> >> 
> >> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> > 
> > but the changes looks reasonable to me.
> > 
> > Signed-off-by: Kevin Tian <kevin.tian@intel.com>
> 
> I translated this to a Reviewed-by, as S-o-b doesn't seem to make
> sense here.
> 
> Konrad - please indicate whether this can also go into 4.5.

Yes. Release-Acked-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> 
> Jan
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] VT-d: don't crash when PTE bits 52 and up are non-zero
  2015-01-07 10:15   ` Jan Beulich
  2015-01-07 15:00     ` Konrad Rzeszutek Wilk
@ 2015-01-08  0:41     ` Tian, Kevin
  1 sibling, 0 replies; 6+ messages in thread
From: Tian, Kevin @ 2015-01-08  0:41 UTC (permalink / raw)
  To: Jan Beulich, Konrad Rzeszutek Wilk; +Cc: Zhang, Yang Z, xen-devel

> From: Jan Beulich [mailto:JBeulich@suse.com]
> Sent: Wednesday, January 07, 2015 6:16 PM
> 
> >>> On 23.12.14 at 07:52, <kevin.tian@intel.com> wrote:
> >>  From: Jan Beulich [mailto:JBeulich@suse.com]
> >> Sent: Friday, December 19, 2014 7:26 PM
> >>
> >> This can (and will) be legitimately the case when sharing page tables
> >> with EPT (more of a problem before p2m_access_rwx became zero, but
> >> still possible even now when other than that is the default for a
> >> guest), leading to an unconditional crash (in print_vtd_entries())
> >> when a DMA remapping fault occurs.
> >
> > could you elaborate the scenarios when bits 52+ are non-zero?
> >
> >>
> >> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> >
> > but the changes looks reasonable to me.
> >
> > Signed-off-by: Kevin Tian <kevin.tian@intel.com>
> 
> I translated this to a Reviewed-by, as S-o-b doesn't seem to make
> sense here.
> 
> Konrad - please indicate whether this can also go into 4.5.
> 
> Jan


sorry for typo. it should be Acked-by. :-)

Thanks
Kevin

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-01-08  0:41 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-19 11:26 [PATCH] VT-d: don't crash when PTE bits 52 and up are non-zero Jan Beulich
2014-12-23  6:52 ` Tian, Kevin
2014-12-23 14:27   ` Jan Beulich
2015-01-07 10:15   ` Jan Beulich
2015-01-07 15:00     ` Konrad Rzeszutek Wilk
2015-01-08  0:41     ` Tian, Kevin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.