diff mbox series

[v4,02/21] IOMMU: simplify unmap-on-error in iommu_map()

Message ID cc4323b2-e074-f86f-eea0-9cd6a802bed8@suse.com (mailing list archive)
State Superseded
Headers show
Series IOMMU: superpage support when not sharing pagetables | expand

Commit Message

Jan Beulich April 25, 2022, 8:32 a.m. UTC
As of 68a8aa5d7264 ("iommu: make map and unmap take a page count,
similar to flush") there's no need anymore to have a loop here.

Suggested-by: Roger Pau Monné <roger.pau@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v3: New.

Comments

Andrew Cooper April 27, 2022, 1:16 p.m. UTC | #1
On 25/04/2022 09:32, Jan Beulich wrote:
> As of 68a8aa5d7264 ("iommu: make map and unmap take a page count,
> similar to flush") there's no need anymore to have a loop here.
>
> Suggested-by: Roger Pau Monné <roger.pau@citrix.com>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> ---
> v3: New.
>
> --- a/xen/drivers/passthrough/iommu.c
> +++ b/xen/drivers/passthrough/iommu.c
> @@ -308,11 +308,9 @@ int iommu_map(struct domain *d, dfn_t df
>                     d->domain_id, dfn_x(dfn_add(dfn, i)),
>                     mfn_x(mfn_add(mfn, i)), rc);
>  
> -        while ( i-- )
> -            /* if statement to satisfy __must_check */
> -            if ( iommu_call(hd->platform_ops, unmap_page, d, dfn_add(dfn, i),
> -                            flush_flags) )
> -                continue;
> +        /* while statement to satisfy __must_check */
> +        while ( iommu_unmap(d, dfn, i, flush_flags) )
> +            break;

How can this possibly be correct?

The map_page() calls are made one 4k page at a time, and this while loop
is undoing every iteration, one 4k page at a time.

Without this while loop, any failure after the first page will end up
not being unmapped.

~Andrew
Jan Beulich April 27, 2022, 2:05 p.m. UTC | #2
On 27.04.2022 15:16, Andrew Cooper wrote:
> On 25/04/2022 09:32, Jan Beulich wrote:
>> --- a/xen/drivers/passthrough/iommu.c
>> +++ b/xen/drivers/passthrough/iommu.c
>> @@ -308,11 +308,9 @@ int iommu_map(struct domain *d, dfn_t df
>>                     d->domain_id, dfn_x(dfn_add(dfn, i)),
>>                     mfn_x(mfn_add(mfn, i)), rc);
>>  
>> -        while ( i-- )
>> -            /* if statement to satisfy __must_check */
>> -            if ( iommu_call(hd->platform_ops, unmap_page, d, dfn_add(dfn, i),
>> -                            flush_flags) )
>> -                continue;
>> +        /* while statement to satisfy __must_check */
>> +        while ( iommu_unmap(d, dfn, i, flush_flags) )
>> +            break;
> 
> How can this possibly be correct?
> 
> The map_page() calls are made one 4k page at a time, and this while loop
> is undoing every iteration, one 4k page at a time.
> 
> Without this while loop, any failure after the first page will end up
> not being unmapped.

There's no real "while loop" here, it's effectively

        if ( iommu_unmap(d, dfn, i, flush_flags) )
            /* nothing */;

just that I wanted to avoid the empty body (but I could switch if
that's preferred).

Note that the 3rd argument to iommu_unmap() is i, not 1.

But I have to admit that I also have trouble interpreting your last
sentence - how would it matter if there was no code here at all? Or
did you maybe mean "With ..." instead of "Without ..."?

Jan
Roger Pau Monne May 3, 2022, 10:25 a.m. UTC | #3
On Mon, Apr 25, 2022 at 10:32:10AM +0200, Jan Beulich wrote:
> As of 68a8aa5d7264 ("iommu: make map and unmap take a page count,
> similar to flush") there's no need anymore to have a loop here.
> 
> Suggested-by: Roger Pau Monné <roger.pau@citrix.com>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

I wonder whether we should have a macro to ignore returns from
__must_check attributed functions.  Ie:

#define IGNORE_RETURN(exp) while ( exp ) break;

As to avoid confusion (and having to reason) whether the usage of
while is correct.  I always find it confusing to assert such loop
expressions are correct.

Thanks, Roger.
Jan Beulich May 3, 2022, 2:37 p.m. UTC | #4
On 03.05.2022 12:25, Roger Pau Monné wrote:
> On Mon, Apr 25, 2022 at 10:32:10AM +0200, Jan Beulich wrote:
>> As of 68a8aa5d7264 ("iommu: make map and unmap take a page count,
>> similar to flush") there's no need anymore to have a loop here.
>>
>> Suggested-by: Roger Pau Monné <roger.pau@citrix.com>
>> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> 
> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

Thanks.

> I wonder whether we should have a macro to ignore returns from
> __must_check attributed functions.  Ie:
> 
> #define IGNORE_RETURN(exp) while ( exp ) break;
> 
> As to avoid confusion (and having to reason) whether the usage of
> while is correct.  I always find it confusing to assert such loop
> expressions are correct.

I've been considering some form of wrapper macro (not specifically
the one you suggest), but I'm of two minds: On one hand I agree it
would help readers, but otoh I fear it may make it more attractive
to actually override the __must_check (which really ought to be an
exception).

Jan
Roger Pau Monne May 3, 2022, 4:22 p.m. UTC | #5
On Tue, May 03, 2022 at 04:37:29PM +0200, Jan Beulich wrote:
> On 03.05.2022 12:25, Roger Pau Monné wrote:
> > On Mon, Apr 25, 2022 at 10:32:10AM +0200, Jan Beulich wrote:
> >> As of 68a8aa5d7264 ("iommu: make map and unmap take a page count,
> >> similar to flush") there's no need anymore to have a loop here.
> >>
> >> Suggested-by: Roger Pau Monné <roger.pau@citrix.com>
> >> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> > 
> > Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
> 
> Thanks.
> 
> > I wonder whether we should have a macro to ignore returns from
> > __must_check attributed functions.  Ie:
> > 
> > #define IGNORE_RETURN(exp) while ( exp ) break;
> > 
> > As to avoid confusion (and having to reason) whether the usage of
> > while is correct.  I always find it confusing to assert such loop
> > expressions are correct.
> 
> I've been considering some form of wrapper macro (not specifically
> the one you suggest), but I'm of two minds: On one hand I agree it
> would help readers, but otoh I fear it may make it more attractive
> to actually override the __must_check (which really ought to be an
> exception).

Well, I think anyone reviewing the code would realize that the error
is being ignored, and hence check that this is actually intended.

Thanks, Roger.
diff mbox series

Patch

--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -308,11 +308,9 @@  int iommu_map(struct domain *d, dfn_t df
                    d->domain_id, dfn_x(dfn_add(dfn, i)),
                    mfn_x(mfn_add(mfn, i)), rc);
 
-        while ( i-- )
-            /* if statement to satisfy __must_check */
-            if ( iommu_call(hd->platform_ops, unmap_page, d, dfn_add(dfn, i),
-                            flush_flags) )
-                continue;
+        /* while statement to satisfy __must_check */
+        while ( iommu_unmap(d, dfn, i, flush_flags) )
+            break;
 
         if ( !is_hardware_domain(d) )
             domain_crash(d);