|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v4 06/10] memory: batch processing in acquire_resource()
On 03.07.2020 13:17, Julien Grall wrote:
> Hi,
>
> On 03/07/2020 11:52, Paul Durrant wrote:
>>> -----Original Message-----
>>> From: Julien Grall <julien@xxxxxxx>
>>> Sent: 03 July 2020 11:36
>>> To: Michał Leszczyński <michal.leszczynski@xxxxxxx>;
>>> xen-devel@xxxxxxxxxxxxxxxxxxxx
>>> Cc: luwei.kang@xxxxxxxxx; tamas.lengyel@xxxxxxxxx; Andrew Cooper
>>> <andrew.cooper3@xxxxxxxxxx>; George
>>> Dunlap <george.dunlap@xxxxxxxxxx>; Ian Jackson <ian.jackson@xxxxxxxxxxxxx>;
>>> Jan Beulich
>>> <jbeulich@xxxxxxxx>; Stefano Stabellini <sstabellini@xxxxxxxxxx>; Wei Liu
>>> <wl@xxxxxxx>; paul@xxxxxxx
>>> Subject: Re: [PATCH v4 06/10] memory: batch processing in acquire_resource()
>>>
>>> (+ Paul as the author XENMEM_acquire_resource)
>>>
>>> Hi,
>>>
>>> On 30/06/2020 13:33, Michał Leszczyński wrote:
>>>> From: Michal Leszczynski <michal.leszczynski@xxxxxxx>
>>>>
>>>> Allow to acquire large resources by allowing acquire_resource()
>>>> to process items in batches, using hypercall continuation.
>>>>
>>>> Signed-off-by: Michal Leszczynski <michal.leszczynski@xxxxxxx>
>>>> ---
>>>> xen/common/memory.c | 32 +++++++++++++++++++++++++++++---
>>>> 1 file changed, 29 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/xen/common/memory.c b/xen/common/memory.c
>>>> index 714077c1e5..3ab06581a2 100644
>>>> --- a/xen/common/memory.c
>>>> +++ b/xen/common/memory.c
>>>> @@ -1046,10 +1046,12 @@ static int acquire_grant_table(struct domain *d,
>>>> unsigned int id,
>>>> }
>>>>
>>>> static int acquire_resource(
>>>> - XEN_GUEST_HANDLE_PARAM(xen_mem_acquire_resource_t) arg)
>>>> + XEN_GUEST_HANDLE_PARAM(xen_mem_acquire_resource_t) arg,
>>>> + unsigned long *start_extent)
>>>> {
>>>> struct domain *d, *currd = current->domain;
>>>> xen_mem_acquire_resource_t xmar;
>>>> + uint32_t total_frames;
>>>> /*
>>>> * The mfn_list and gfn_list (below) arrays are ok on stack for the
>>>> * moment since they are small, but if they need to grow in future
>>>> @@ -1077,8 +1079,17 @@ static int acquire_resource(
>>>> return 0;
>>>> }
>>>>
>>>> + total_frames = xmar.nr_frames;
>>>
>>> On 32-bit, the start_extent would be 26-bits wide which is not enough to
>>> cover all the xmar.nr_frames. Therefore, you want that check that it is
>>> possible to encode a continuation. Something like:
>>>
>>> /* Is the size too large for us to encode a continuation? */
>>> if ( unlikely(xmar.nr_frames > (UINT_MAX >> MEMOP_EXTENT_SHIFT)) )
>>>
>>>> +
>>>> + if ( *start_extent ) > + {
>>>> + xmar.frame += *start_extent;
>>>> + xmar.nr_frames -= *start_extent;
>>>
>>> As start_extent is exposed to the guest, you want to check if it is not
>>> bigger than xmar.nr_frames.
>>>
>>>> + guest_handle_add_offset(xmar.frame_list, *start_extent);
>>>> + }
>>>> +
>>>> if ( xmar.nr_frames > ARRAY_SIZE(mfn_list) )
>>>> - return -E2BIG;
>>>> + xmar.nr_frames = ARRAY_SIZE(mfn_list);
>>>
>>> The documentation of the hypercall suggests that if you pass NULL, then
>>> it will return the maximum number value for nr_frames supported by the
>>> implementation. So technically a domain cannot use more than
>>> ARRAY_SIZE(mfn_list).
>>>
>>> However, you new addition conflict with the documentation. Can you
>>> clarify how a domain will know that it can use more than
>>> ARRAY_SIZE(mfn_list)?
>>
>> The domain should not need to know. It should be told the maximum number of
>> frames of the type it wants. If we have to carve that up into batches inside
>> Xen then the caller should not need to care, right?
>
> In the current implementation, we tell the guest how many frames it can
> request in a batch. This number may be much smaller that the maximum
> number of frames of the type.
>
> Furthermore this value is not tie to the xmar.type. Therefore, it is
> valid for a guest to call this hypercall only once at boot to figure out
> the maximum batch.
>
> So while the change you suggest looks a good idea, I don't think it is
> possible to do that with the current hypercall.
Doesn't the limit simply change to UINT_MAX >> MEMOP_EXTENT_SHIFT,
which then is what should be reported?
>>>> @@ -1135,6 +1146,14 @@ static int acquire_resource(
>>>> }
>>>> }
>>>>
>>>> + if ( !rc )
>>>> + {
>>>> + *start_extent += xmar.nr_frames;
>>>> +
>>>> + if ( *start_extent != total_frames )
>>>> + rc = -ERESTART;
>>>> + }
>>>> +
>>>> out:
>>>> rcu_unlock_domain(d);
>>>>
>>>> @@ -1600,7 +1619,14 @@ long do_memory_op(unsigned long cmd,
>>>> XEN_GUEST_HANDLE_PARAM(void) arg)
>>>>
>>>> case XENMEM_acquire_resource:
>>>> rc = acquire_resource(
>>>> - guest_handle_cast(arg, xen_mem_acquire_resource_t));
>>>> + guest_handle_cast(arg, xen_mem_acquire_resource_t),
>>>> + &start_extent);
>>>
>>> Hmmm... it looks like we forgot to check that start_extent is always 0
>>> when the hypercall was added.
>>>
>>> As this is exposed to the guest, it technically means that there no
>>> guarantee that start_extent will always be 0.
>>>
>>
>> I don't follow. A start extent != 0 means you are in a continuation. How can
>> you check for 0 without breaking continuations?
>
> I think you misundertood my point. My point is we never checked that
> start_extent was 0. So a guest could validly pass a non-zero value to
> start_extent and not break on older Xen release.
>
> When this patch will be merged, such guest would behave differently. Or
> did I miss any check/documentation for the start_extent value?
I think we may have done the same in the past already when enabling
sub-ops for use of continuations. A guest specifying a non-zero
start_extent itself is effectively a request for an undefined sub-op.
With, as a result, undefined behavior.
Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |