|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v5 6/8] common/grant_table: batch flush I/O TLB
On 10.09.2020 16:17, Paul Durrant wrote:
>> From: Jan Beulich <jbeulich@xxxxxxxx>
>> Sent: 10 September 2020 14:49
>>
>> On 07.09.2020 09:40, Paul Durrant wrote:
>>> --- a/xen/common/grant_table.c
>>> +++ b/xen/common/grant_table.c
>>> @@ -241,7 +241,13 @@ struct gnttab_unmap_common {
>>> grant_ref_t ref;
>>> };
>>>
>>> -/* Number of unmap operations that are done between each tlb flush */
>>> +/* Number of map operations that are done between each pre-emption check */
>>> +#define GNTTAB_MAP_BATCH_SIZE 32
>>> +
>>> +/*
>>> + * Number of unmap operations that are done between each tlb flush and
>>> + * pre-emption check.
>>> + */
>>> #define GNTTAB_UNMAP_BATCH_SIZE 32
>>
>> Interesting - I don't think I've ever seen preemption spelled like
>> this (with a hyphen). In the interest of grep-ability, would you
>> mind changing to the more "conventional" spelling? Albeit I now
>> notice we have two such spellings in the tree already ...
>>
>
> Sure, I'll change it.
>
>>> @@ -979,7 +985,7 @@ static unsigned int mapkind(
>>>
>>> static void
>>> map_grant_ref(
>>> - struct gnttab_map_grant_ref *op)
>>> + struct gnttab_map_grant_ref *op, bool do_flush, unsigned int
>>> *flush_flags)
>>
>> Why two parameters? Simply pass NULL for singletons instead? Although,
>> you'd need another local variable then, which maybe isn't overly much
>> nicer.
>>
>
> No, I think the extra arg is clearer.
>
>>> @@ -1319,29 +1324,60 @@ static long
>>> gnttab_map_grant_ref(
>>> XEN_GUEST_HANDLE_PARAM(gnttab_map_grant_ref_t) uop, unsigned int count)
>>> {
>>> - int i;
>>> - struct gnttab_map_grant_ref op;
>>> + struct domain *currd = current->domain;
>>
>> Is this a worthwhile variable to have in this case? It's used
>> exactly once, granted in the loop body, but still not the inner
>> one.
>>
>
> I thought it was nicer for consistency with the unmap function (where curd is
> used more than once) but I'll drop it.
>
>>> + unsigned int done = 0;
>>> + int rc = 0;
>>>
>>> - for ( i = 0; i < count; i++ )
>>> + while ( count )
>>> {
>>> - if ( i && hypercall_preempt_check() )
>>> - return i;
>>> + unsigned int i, c = min_t(unsigned int, count,
>>> GNTTAB_MAP_BATCH_SIZE);
>>> + unsigned int flush_flags = 0;
>>>
>>> - if ( unlikely(__copy_from_guest_offset(&op, uop, i, 1)) )
>>> - return -EFAULT;
>>> + for ( i = 0; i < c; i++ )
>>> + {
>>> + struct gnttab_map_grant_ref op;
>>>
>>> - map_grant_ref(&op);
>>> + if ( unlikely(__copy_from_guest(&op, uop, 1)) )
>>> + {
>>> + rc = -EFAULT;
>>> + break;
>>> + }
>>>
>>> - if ( unlikely(__copy_to_guest_offset(uop, i, &op, 1)) )
>>> - return -EFAULT;
>>> + map_grant_ref(&op, c == 1, &flush_flags);
>>> +
>>> + if ( unlikely(__copy_to_guest(uop, &op, 1)) )
>>> + {
>>> + rc = -EFAULT;
>>> + break;
>>> + }
>>> +
>>> + guest_handle_add_offset(uop, 1);
>>> + }
>>> +
>>> + if ( c > 1 )
>>> + {
>>> + int err = iommu_iotlb_flush_all(currd, flush_flags);
>>
>> There's still some double flushing involved in the error case here.
>> Trying to eliminate this (by having map_grant_ref() write zero
>> into *flush_flags) may not be overly important, but I thought I'd
>> still mention it.
>>
>
> This only kicks in if there's more than one operation and is it safe to
> squash the flush_flags if some ops succeed and others fail? If all ops fail
> then flush_flags should still be zero because the call to iommu_map() is the
> last failure point in map_grant_ref() anyway.
Well, yes, not a common thing to run into. With the small changes
further up
Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |