Re: [Xen-devel] [PATCH 1/2] amd-iommu: use a bitfield for PTE/PDE
> -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
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
> -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
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
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, -