Re: [Xen-devel] [PATCH 1/2] amd-iommu: use a bitfield for PTE/PDE

2019-02-13 Thread Paul Durrant
> -Original Message-
> From: Xen-devel [mailto:xen-devel-boun...@lists.xenproject.org] On Behalf
> Of Woods, Brian
> Sent: 13 February 2019 15:34
> To: Paul Durrant ; xen-devel@lists.xenproject.org
> Cc: Andrew Cooper ; Wei Liu
> ; Jan Beulich ; Suthikulpanit,
> Suravee ; Roger Pau Monne
> 
> Subject: Re: [Xen-devel] [PATCH 1/2] amd-iommu: use a bitfield for PTE/PDE
> 
> On 2/13/19 3:45 AM, Paul Durrant wrote:
> >> -Original Message-
> >> From: Woods, Brian [mailto:brian.wo...@amd.com]
> >> Sent: 12 February 2019 20:14
> >> To: Paul Durrant ; xen-
> de...@lists.xenproject.org
> >> Cc: Suthikulpanit, Suravee ; Jan Beulich
> >> ; Andrew Cooper ; Wei Liu
> >> ; Roger Pau Monne 
> >> Subject: Re: [PATCH 1/2] amd-iommu: use a bitfield for PTE/PDE
> >>
> >> On 2/4/19 5:19 AM, Paul Durrant wrote:
> >>> The current use of get/set_field_from/in_reg_u32() is both inefficient
> >> and
> >>> requires some ugly casting.
> >>>
> >>> This patch defines a new bitfield structure (amd_iommu_pte) and uses
> >> this
> >>> structure in all PTE/PDE manipulation, resulting in much more readable
> >>> and compact code.
> >>>
> >>> NOTE: This commit also fixes one malformed comment in
> >>> set_iommu_pte_present().
> >>>
> >>> Signed-off-by: Paul Durrant 
> >>
> >> Sorry about the delay.
> >>
> >> Nitpick here, but I'd rather have !!IOMMUF_{writable,readable} than
> >> true.
> >
> > That's pretty ugly. How about I pass an OR of the flags through to lower
> level functions rather than a pair of bools? If you're ok with that I'll
> send a v2.
> >
> >Paul
> >
> 
> There's no need for a v2 based on that, that's just me nitpicking.
> There's no real nice way to do it without turning
> IOMMUF_{writable,readable} into bools or your suggested way which has
> more code to decode a flag.  Assuming everyone else is ok with the
> patches as are, it's fine.  If there's going to be a v2 for other
> reasons, I'll just leave it up to your discretion (other people may have
> stronger opinions about it anyway).
> 

Ok. Thanks Brian,

  Paul
___
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

Re: [Xen-devel] [PATCH 1/2] amd-iommu: use a bitfield for PTE/PDE

2019-02-13 Thread Woods, Brian
On 2/13/19 3:45 AM, Paul Durrant wrote:
>> -Original Message-
>> From: Woods, Brian [mailto:brian.wo...@amd.com]
>> Sent: 12 February 2019 20:14
>> To: Paul Durrant ; xen-devel@lists.xenproject.org
>> Cc: Suthikulpanit, Suravee ; Jan Beulich
>> ; Andrew Cooper ; Wei Liu
>> ; Roger Pau Monne 
>> Subject: Re: [PATCH 1/2] amd-iommu: use a bitfield for PTE/PDE
>>
>> On 2/4/19 5:19 AM, Paul Durrant wrote:
>>> The current use of get/set_field_from/in_reg_u32() is both inefficient
>> and
>>> requires some ugly casting.
>>>
>>> This patch defines a new bitfield structure (amd_iommu_pte) and uses
>> this
>>> structure in all PTE/PDE manipulation, resulting in much more readable
>>> and compact code.
>>>
>>> NOTE: This commit also fixes one malformed comment in
>>> set_iommu_pte_present().
>>>
>>> Signed-off-by: Paul Durrant 
>>
>> Sorry about the delay.
>>
>> Nitpick here, but I'd rather have !!IOMMUF_{writable,readable} than
>> true.
> 
> That's pretty ugly. How about I pass an OR of the flags through to lower 
> level functions rather than a pair of bools? If you're ok with that I'll send 
> a v2.
> 
>Paul
> 

There's no need for a v2 based on that, that's just me nitpicking. 
There's no real nice way to do it without turning 
IOMMUF_{writable,readable} into bools or your suggested way which has 
more code to decode a flag.  Assuming everyone else is ok with the 
patches as are, it's fine.  If there's going to be a v2 for other 
reasons, I'll just leave it up to your discretion (other people may have 
stronger opinions about it anyway).

Brian

>>   Not worth a revision if there isn't anything else though (and is
>> debatable).
>>
>> Acked-by: Brian Woods 
>>
>>> ---
>>> Cc: Suravee Suthikulpanit 
>>> Cc: Brian Woods 
>>> Cc: Jan Beulich 
>>> Cc: Andrew Cooper 
>>> Cc: Wei Liu 
>>> Cc: "Roger Pau Monné" 
>>> ---
>>>xen/drivers/passthrough/amd/iommu_map.c   | 143 --
>>>xen/drivers/passthrough/amd/pci_amd_iommu.c   |  50 +++---
>>>xen/include/asm-x86/hvm/svm/amd-iommu-defs.h  |  47 ++
>>>xen/include/asm-x86/hvm/svm/amd-iommu-proto.h |  15 --
>>>4 files changed, 64 insertions(+), 191 deletions(-)
>>>
>>> diff --git a/xen/drivers/passthrough/amd/iommu_map.c
>> b/xen/drivers/passthrough/amd/iommu_map.c
>>> index 67329b0c95..5fda6063df 100644
>>> --- a/xen/drivers/passthrough/amd/iommu_map.c
>>> +++ b/xen/drivers/passthrough/amd/iommu_map.c
>>> @@ -38,100 +38,45 @@ static unsigned int pfn_to_pde_idx(unsigned long
>> pfn, unsigned int level)
>>>static unsigned int clear_iommu_pte_present(unsigned long l1_mfn,
>>>unsigned long dfn)
>>>{
>>> -uint64_t *table, *pte;
>>> +struct amd_iommu_pte *table, *pte;
>>>unsigned int flush_flags;
>>>
>>>table = map_domain_page(_mfn(l1_mfn));
>>> +pte = &table[pfn_to_pde_idx(dfn, 1)];
>>>
>>> -pte = (table + pfn_to_pde_idx(dfn, 1));
>>> +flush_flags = pte->pr ? IOMMU_FLUSHF_modified : 0;
>>> +memset(pte, 0, sizeof(*pte));
>>>
>>> -flush_flags = get_field_from_reg_u32(*pte, IOMMU_PTE_PRESENT_MASK,
>>> - IOMMU_PTE_PRESENT_SHIFT) ?
>>> - IOMMU_FLUSHF_modified : 0;
>>> -
>>> -*pte = 0;
>>>unmap_domain_page(table);
>>>
>>>return flush_flags;
>>>}
>>>
>>> -static unsigned int set_iommu_pde_present(uint32_t *pde,
>>> +static unsigned int set_iommu_pde_present(struct amd_iommu_pte *pte,
>>>  unsigned long next_mfn,
>>>  unsigned int next_level,
>> bool iw,
>>>  bool ir)
>>>{
>>> -uint64_t maddr_next;
>>> -uint32_t addr_lo, addr_hi, entry;
>>> -bool old_present;
>>>unsigned int flush_flags = IOMMU_FLUSHF_added;
>>>
>>> -maddr_next = __pfn_to_paddr(next_mfn);
>>> -
>>> -old_present = get_field_from_reg_u32(pde[0],
>> IOMMU_PTE_PRESENT_MASK,
>>> - IOMMU_PTE_PRESENT_SHIFT);
>>> -if ( old_present )
>>> -{
>>> -bool old_r, old_w;
>>> -unsigned int old_level;
>>> -uint64_t maddr_old;
>>> -
>>> -addr_hi = get_field_from_reg_u32(pde[1],
>>> - IOMMU_PTE_ADDR_HIGH_MASK,
>>> - IOMMU_PTE_ADDR_HIGH_SHIFT);
>>> -addr_lo = get_field_from_reg_u32(pde[0],
>>> - IOMMU_PTE_ADDR_LOW_MASK,
>>> - IOMMU_PTE_ADDR_LOW_SHIFT);
>>> -old_level = get_field_from_reg_u32(pde[0],
>>> -   IOMMU_PDE_NEXT_LEVEL_MASK,
>>> -   IOMMU_PDE_NEXT_LEVEL_SHIFT);
>>> -old_w = get_field_from_reg_u32(pde[1],
>>> -
>> IOMMU_PTE_IO_WRITE_PERMISSION_MASK,
>>> -
>> IOMMU_PTE_IO_WRITE_

Re: [Xen-devel] [PATCH 1/2] amd-iommu: use a bitfield for PTE/PDE

2019-02-13 Thread Paul Durrant
> -Original Message-
> From: Woods, Brian [mailto:brian.wo...@amd.com]
> Sent: 12 February 2019 20:14
> To: Paul Durrant ; xen-devel@lists.xenproject.org
> Cc: Suthikulpanit, Suravee ; Jan Beulich
> ; Andrew Cooper ; Wei Liu
> ; Roger Pau Monne 
> Subject: Re: [PATCH 1/2] amd-iommu: use a bitfield for PTE/PDE
> 
> On 2/4/19 5:19 AM, Paul Durrant wrote:
> > The current use of get/set_field_from/in_reg_u32() is both inefficient
> and
> > requires some ugly casting.
> >
> > This patch defines a new bitfield structure (amd_iommu_pte) and uses
> this
> > structure in all PTE/PDE manipulation, resulting in much more readable
> > and compact code.
> >
> > NOTE: This commit also fixes one malformed comment in
> >set_iommu_pte_present().
> >
> > Signed-off-by: Paul Durrant 
> 
> Sorry about the delay.
> 
> Nitpick here, but I'd rather have !!IOMMUF_{writable,readable} than
> true.

That's pretty ugly. How about I pass an OR of the flags through to lower level 
functions rather than a pair of bools? If you're ok with that I'll send a v2.

  Paul

>  Not worth a revision if there isn't anything else though (and is
> debatable).
> 
> Acked-by: Brian Woods 
> 
> > ---
> > Cc: Suravee Suthikulpanit 
> > Cc: Brian Woods 
> > Cc: Jan Beulich 
> > Cc: Andrew Cooper 
> > Cc: Wei Liu 
> > Cc: "Roger Pau Monné" 
> > ---
> >   xen/drivers/passthrough/amd/iommu_map.c   | 143 --
> >   xen/drivers/passthrough/amd/pci_amd_iommu.c   |  50 +++---
> >   xen/include/asm-x86/hvm/svm/amd-iommu-defs.h  |  47 ++
> >   xen/include/asm-x86/hvm/svm/amd-iommu-proto.h |  15 --
> >   4 files changed, 64 insertions(+), 191 deletions(-)
> >
> > diff --git a/xen/drivers/passthrough/amd/iommu_map.c
> b/xen/drivers/passthrough/amd/iommu_map.c
> > index 67329b0c95..5fda6063df 100644
> > --- a/xen/drivers/passthrough/amd/iommu_map.c
> > +++ b/xen/drivers/passthrough/amd/iommu_map.c
> > @@ -38,100 +38,45 @@ static unsigned int pfn_to_pde_idx(unsigned long
> pfn, unsigned int level)
> >   static unsigned int clear_iommu_pte_present(unsigned long l1_mfn,
> >   unsigned long dfn)
> >   {
> > -uint64_t *table, *pte;
> > +struct amd_iommu_pte *table, *pte;
> >   unsigned int flush_flags;
> >
> >   table = map_domain_page(_mfn(l1_mfn));
> > +pte = &table[pfn_to_pde_idx(dfn, 1)];
> >
> > -pte = (table + pfn_to_pde_idx(dfn, 1));
> > +flush_flags = pte->pr ? IOMMU_FLUSHF_modified : 0;
> > +memset(pte, 0, sizeof(*pte));
> >
> > -flush_flags = get_field_from_reg_u32(*pte, IOMMU_PTE_PRESENT_MASK,
> > - IOMMU_PTE_PRESENT_SHIFT) ?
> > - IOMMU_FLUSHF_modified : 0;
> > -
> > -*pte = 0;
> >   unmap_domain_page(table);
> >
> >   return flush_flags;
> >   }
> >
> > -static unsigned int set_iommu_pde_present(uint32_t *pde,
> > +static unsigned int set_iommu_pde_present(struct amd_iommu_pte *pte,
> > unsigned long next_mfn,
> > unsigned int next_level,
> bool iw,
> > bool ir)
> >   {
> > -uint64_t maddr_next;
> > -uint32_t addr_lo, addr_hi, entry;
> > -bool old_present;
> >   unsigned int flush_flags = IOMMU_FLUSHF_added;
> >
> > -maddr_next = __pfn_to_paddr(next_mfn);
> > -
> > -old_present = get_field_from_reg_u32(pde[0],
> IOMMU_PTE_PRESENT_MASK,
> > - IOMMU_PTE_PRESENT_SHIFT);
> > -if ( old_present )
> > -{
> > -bool old_r, old_w;
> > -unsigned int old_level;
> > -uint64_t maddr_old;
> > -
> > -addr_hi = get_field_from_reg_u32(pde[1],
> > - IOMMU_PTE_ADDR_HIGH_MASK,
> > - IOMMU_PTE_ADDR_HIGH_SHIFT);
> > -addr_lo = get_field_from_reg_u32(pde[0],
> > - IOMMU_PTE_ADDR_LOW_MASK,
> > - IOMMU_PTE_ADDR_LOW_SHIFT);
> > -old_level = get_field_from_reg_u32(pde[0],
> > -   IOMMU_PDE_NEXT_LEVEL_MASK,
> > -   IOMMU_PDE_NEXT_LEVEL_SHIFT);
> > -old_w = get_field_from_reg_u32(pde[1],
> > -
> IOMMU_PTE_IO_WRITE_PERMISSION_MASK,
> > -
> IOMMU_PTE_IO_WRITE_PERMISSION_SHIFT);
> > -old_r = get_field_from_reg_u32(pde[1],
> > -
> IOMMU_PTE_IO_READ_PERMISSION_MASK,
> > -
> IOMMU_PTE_IO_READ_PERMISSION_SHIFT);
> > -
> > -maddr_old = ((uint64_t)addr_hi << 32) |
> > -((uint64_t)addr_lo << PAGE_SHIFT);
> > -
> > -if ( maddr_old != maddr_next || iw != old_w || ir != old_r ||
> > - old_level != next_level )
> > +if ( pte->pr &&
> > + (pte->mfn != next_mfn ||
> > +  pte->iw != iw ||
> > +  pte->ir != ir ||
> > +   

Re: [Xen-devel] [PATCH 1/2] amd-iommu: use a bitfield for PTE/PDE

2019-02-12 Thread Woods, Brian
On 2/4/19 5:19 AM, Paul Durrant wrote:
> The current use of get/set_field_from/in_reg_u32() is both inefficient and
> requires some ugly casting.
> 
> This patch defines a new bitfield structure (amd_iommu_pte) and uses this
> structure in all PTE/PDE manipulation, resulting in much more readable
> and compact code.
> 
> NOTE: This commit also fixes one malformed comment in
>set_iommu_pte_present().
> 
> Signed-off-by: Paul Durrant 

Sorry about the delay.

Nitpick here, but I'd rather have !!IOMMUF_{writable,readable} than 
true.  Not worth a revision if there isn't anything else though (and is 
debatable).

Acked-by: Brian Woods 

> ---
> Cc: Suravee Suthikulpanit 
> Cc: Brian Woods 
> Cc: Jan Beulich 
> Cc: Andrew Cooper 
> Cc: Wei Liu 
> Cc: "Roger Pau Monné" 
> ---
>   xen/drivers/passthrough/amd/iommu_map.c   | 143 --
>   xen/drivers/passthrough/amd/pci_amd_iommu.c   |  50 +++---
>   xen/include/asm-x86/hvm/svm/amd-iommu-defs.h  |  47 ++
>   xen/include/asm-x86/hvm/svm/amd-iommu-proto.h |  15 --
>   4 files changed, 64 insertions(+), 191 deletions(-)
> 
> diff --git a/xen/drivers/passthrough/amd/iommu_map.c 
> b/xen/drivers/passthrough/amd/iommu_map.c
> index 67329b0c95..5fda6063df 100644
> --- a/xen/drivers/passthrough/amd/iommu_map.c
> +++ b/xen/drivers/passthrough/amd/iommu_map.c
> @@ -38,100 +38,45 @@ static unsigned int pfn_to_pde_idx(unsigned long pfn, 
> unsigned int level)
>   static unsigned int clear_iommu_pte_present(unsigned long l1_mfn,
>   unsigned long dfn)
>   {
> -uint64_t *table, *pte;
> +struct amd_iommu_pte *table, *pte;
>   unsigned int flush_flags;
>   
>   table = map_domain_page(_mfn(l1_mfn));
> +pte = &table[pfn_to_pde_idx(dfn, 1)];
>   
> -pte = (table + pfn_to_pde_idx(dfn, 1));
> +flush_flags = pte->pr ? IOMMU_FLUSHF_modified : 0;
> +memset(pte, 0, sizeof(*pte));
>   
> -flush_flags = get_field_from_reg_u32(*pte, IOMMU_PTE_PRESENT_MASK,
> - IOMMU_PTE_PRESENT_SHIFT) ?
> - IOMMU_FLUSHF_modified : 0;
> -
> -*pte = 0;
>   unmap_domain_page(table);
>   
>   return flush_flags;
>   }
>   
> -static unsigned int set_iommu_pde_present(uint32_t *pde,
> +static unsigned int set_iommu_pde_present(struct amd_iommu_pte *pte,
> unsigned long next_mfn,
> unsigned int next_level, bool iw,
> bool ir)
>   {
> -uint64_t maddr_next;
> -uint32_t addr_lo, addr_hi, entry;
> -bool old_present;
>   unsigned int flush_flags = IOMMU_FLUSHF_added;
>   
> -maddr_next = __pfn_to_paddr(next_mfn);
> -
> -old_present = get_field_from_reg_u32(pde[0], IOMMU_PTE_PRESENT_MASK,
> - IOMMU_PTE_PRESENT_SHIFT);
> -if ( old_present )
> -{
> -bool old_r, old_w;
> -unsigned int old_level;
> -uint64_t maddr_old;
> -
> -addr_hi = get_field_from_reg_u32(pde[1],
> - IOMMU_PTE_ADDR_HIGH_MASK,
> - IOMMU_PTE_ADDR_HIGH_SHIFT);
> -addr_lo = get_field_from_reg_u32(pde[0],
> - IOMMU_PTE_ADDR_LOW_MASK,
> - IOMMU_PTE_ADDR_LOW_SHIFT);
> -old_level = get_field_from_reg_u32(pde[0],
> -   IOMMU_PDE_NEXT_LEVEL_MASK,
> -   IOMMU_PDE_NEXT_LEVEL_SHIFT);
> -old_w = get_field_from_reg_u32(pde[1],
> -   IOMMU_PTE_IO_WRITE_PERMISSION_MASK,
> -   IOMMU_PTE_IO_WRITE_PERMISSION_SHIFT);
> -old_r = get_field_from_reg_u32(pde[1],
> -   IOMMU_PTE_IO_READ_PERMISSION_MASK,
> -   IOMMU_PTE_IO_READ_PERMISSION_SHIFT);
> -
> -maddr_old = ((uint64_t)addr_hi << 32) |
> -((uint64_t)addr_lo << PAGE_SHIFT);
> -
> -if ( maddr_old != maddr_next || iw != old_w || ir != old_r ||
> - old_level != next_level )
> +if ( pte->pr &&
> + (pte->mfn != next_mfn ||
> +  pte->iw != iw ||
> +  pte->ir != ir ||
> +  pte->next_level != next_level) )
>   flush_flags |= IOMMU_FLUSHF_modified;
> -}
>   
> -addr_lo = maddr_next & DMA_32BIT_MASK;
> -addr_hi = maddr_next >> 32;
> -
> -/* enable read/write permissions,which will be enforced at the PTE */
> -set_field_in_reg_u32(addr_hi, 0,
> - IOMMU_PDE_ADDR_HIGH_MASK,
> - IOMMU_PDE_ADDR_HIGH_SHIFT, &entry);
> -set_field_in_reg_u32(iw, entry,
> - IOMMU_PDE_IO_WRITE_PERMISSION_MASK,
> -  

[Xen-devel] [PATCH 1/2] amd-iommu: use a bitfield for PTE/PDE

2019-02-04 Thread Paul Durrant
The current use of get/set_field_from/in_reg_u32() is both inefficient and
requires some ugly casting.

This patch defines a new bitfield structure (amd_iommu_pte) and uses this
structure in all PTE/PDE manipulation, resulting in much more readable
and compact code.

NOTE: This commit also fixes one malformed comment in
  set_iommu_pte_present().

Signed-off-by: Paul Durrant 
---
Cc: Suravee Suthikulpanit 
Cc: Brian Woods 
Cc: Jan Beulich 
Cc: Andrew Cooper 
Cc: Wei Liu 
Cc: "Roger Pau Monné" 
---
 xen/drivers/passthrough/amd/iommu_map.c   | 143 --
 xen/drivers/passthrough/amd/pci_amd_iommu.c   |  50 +++---
 xen/include/asm-x86/hvm/svm/amd-iommu-defs.h  |  47 ++
 xen/include/asm-x86/hvm/svm/amd-iommu-proto.h |  15 --
 4 files changed, 64 insertions(+), 191 deletions(-)

diff --git a/xen/drivers/passthrough/amd/iommu_map.c 
b/xen/drivers/passthrough/amd/iommu_map.c
index 67329b0c95..5fda6063df 100644
--- a/xen/drivers/passthrough/amd/iommu_map.c
+++ b/xen/drivers/passthrough/amd/iommu_map.c
@@ -38,100 +38,45 @@ static unsigned int pfn_to_pde_idx(unsigned long pfn, 
unsigned int level)
 static unsigned int clear_iommu_pte_present(unsigned long l1_mfn,
 unsigned long dfn)
 {
-uint64_t *table, *pte;
+struct amd_iommu_pte *table, *pte;
 unsigned int flush_flags;
 
 table = map_domain_page(_mfn(l1_mfn));
+pte = &table[pfn_to_pde_idx(dfn, 1)];
 
-pte = (table + pfn_to_pde_idx(dfn, 1));
+flush_flags = pte->pr ? IOMMU_FLUSHF_modified : 0;
+memset(pte, 0, sizeof(*pte));
 
-flush_flags = get_field_from_reg_u32(*pte, IOMMU_PTE_PRESENT_MASK,
- IOMMU_PTE_PRESENT_SHIFT) ?
- IOMMU_FLUSHF_modified : 0;
-
-*pte = 0;
 unmap_domain_page(table);
 
 return flush_flags;
 }
 
-static unsigned int set_iommu_pde_present(uint32_t *pde,
+static unsigned int set_iommu_pde_present(struct amd_iommu_pte *pte,
   unsigned long next_mfn,
   unsigned int next_level, bool iw,
   bool ir)
 {
-uint64_t maddr_next;
-uint32_t addr_lo, addr_hi, entry;
-bool old_present;
 unsigned int flush_flags = IOMMU_FLUSHF_added;
 
-maddr_next = __pfn_to_paddr(next_mfn);
-
-old_present = get_field_from_reg_u32(pde[0], IOMMU_PTE_PRESENT_MASK,
- IOMMU_PTE_PRESENT_SHIFT);
-if ( old_present )
-{
-bool old_r, old_w;
-unsigned int old_level;
-uint64_t maddr_old;
-
-addr_hi = get_field_from_reg_u32(pde[1],
- IOMMU_PTE_ADDR_HIGH_MASK,
- IOMMU_PTE_ADDR_HIGH_SHIFT);
-addr_lo = get_field_from_reg_u32(pde[0],
- IOMMU_PTE_ADDR_LOW_MASK,
- IOMMU_PTE_ADDR_LOW_SHIFT);
-old_level = get_field_from_reg_u32(pde[0],
-   IOMMU_PDE_NEXT_LEVEL_MASK,
-   IOMMU_PDE_NEXT_LEVEL_SHIFT);
-old_w = get_field_from_reg_u32(pde[1],
-   IOMMU_PTE_IO_WRITE_PERMISSION_MASK,
-   IOMMU_PTE_IO_WRITE_PERMISSION_SHIFT);
-old_r = get_field_from_reg_u32(pde[1],
-   IOMMU_PTE_IO_READ_PERMISSION_MASK,
-   IOMMU_PTE_IO_READ_PERMISSION_SHIFT);
-
-maddr_old = ((uint64_t)addr_hi << 32) |
-((uint64_t)addr_lo << PAGE_SHIFT);
-
-if ( maddr_old != maddr_next || iw != old_w || ir != old_r ||
- old_level != next_level )
+if ( pte->pr &&
+ (pte->mfn != next_mfn ||
+  pte->iw != iw ||
+  pte->ir != ir ||
+  pte->next_level != next_level) )
 flush_flags |= IOMMU_FLUSHF_modified;
-}
 
-addr_lo = maddr_next & DMA_32BIT_MASK;
-addr_hi = maddr_next >> 32;
-
-/* enable read/write permissions,which will be enforced at the PTE */
-set_field_in_reg_u32(addr_hi, 0,
- IOMMU_PDE_ADDR_HIGH_MASK,
- IOMMU_PDE_ADDR_HIGH_SHIFT, &entry);
-set_field_in_reg_u32(iw, entry,
- IOMMU_PDE_IO_WRITE_PERMISSION_MASK,
- IOMMU_PDE_IO_WRITE_PERMISSION_SHIFT, &entry);
-set_field_in_reg_u32(ir, entry,
- IOMMU_PDE_IO_READ_PERMISSION_MASK,
- IOMMU_PDE_IO_READ_PERMISSION_SHIFT, &entry);
-
-/* FC bit should be enabled in PTE, this helps to solve potential
+/*
+ * FC bit should be enabled in PTE, this helps to solve potential
  * issues with ATS devices
  */
-if ( next_level == 0 )
-set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
-