[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v6 1/3] ioreq: switch ioreq page allocation to vmap




On 8/18/26 3:06 PM, Jan Beulich wrote:
> On 20.04.2026 11:38, Julian Vetter wrote:
>> Switch the Xen-side ioreq page mapping from prepare_ring_for_helper() /
>> map_domain_page_global() to explicit vmap(), to ensure vmap_to_page()
>> can recover the struct page_info * uniformly during teardown.
> 
> What's after the comma isn't really the main reason for this patch, is it?
> Describing this aspect ...
> 
>> This is a prerequisite for multi-page ioreq support: the non-buf ioreq
>> region will need to span multiple pages for domains with more vCPUs than
>> fit in a single page, and vmap() is the natural interface for contiguous
>> multi-page Xen VA mappings.
>>
>> In non-debug builds map_domain_page_global() uses the directmap for low
>> MFNs rather than vmap(), so this change has a small overhead in the
>> common case. Debug builds already used vmap() indirectly.
>>
>> With both paths using vmap(), vmap_to_page() can recover the struct
>> page_info * uniformly, so drop the 'page' field from struct ioreq_page
>> and update all callers accordingly.
> 
> ... here (at the bottom) is fully sufficient.
> 
>> Signed-off-by: Julian Vetter <julian.vetter@xxxxxxxxxx>
>> ---
>> Changes in v6:
>> - Updated commit message to clearly specify why these changes are made
>> - Added comment to say that this is {prepare,destroy}_ring_for_helper()
>>    just using vmap_to_page() + v{map,unmap}()
>> - Kept proper ordering in ioreq_server_free_mfn(), first clearing the va
>>    pointer before unmapping
> 
> Yet then you didn't extend the same consideration ...
> 
>> @@ -128,8 +129,13 @@ static void hvm_unmap_ioreq_gfn(struct ioreq_server *s, 
>> bool buf)
>>       if ( gfn_eq(iorp->gfn, INVALID_GFN) )
>>           return;
>>   
>> -    destroy_ring_for_helper(&iorp->va, iorp->page);
>> -    iorp->page = NULL;
>> +    /* Equivalent to destroy_ring_for_helper(), using vmap_to_page(). */
>> +    if ( iorp->va )
>> +    {
>> +        put_page_and_type(vmap_to_page(iorp->va));
>> +        vunmap(iorp->va);
>> +        iorp->va = NULL;
>> +    }
> 
> ... to here. (Really we should perhaps introduce VUNMAP(), much like we
> have XFREE(), XVFREE(), etc.)
> 
> Further the ordering doesn't match destroy_ring_for_helper(), which unmaps
> first and only then drops the page refs.
> 
>> @@ -162,12 +171,40 @@ static int hvm_map_ioreq_gfn(struct ioreq_server *s, 
>> bool buf)
>>       if ( gfn_eq(iorp->gfn, INVALID_GFN) )
>>           return -ENOMEM;
>>   
>> -    rc = prepare_ring_for_helper(d, gfn_x(iorp->gfn), &iorp->page,
>> -                                 &iorp->va);
>> -
>> +    /*
>> +     * Equivalent to prepare_ring_for_helper() using vmap(). Using vmap()
>> +     * rather than map_domain_page_global() ensures vmap_to_page() can
>> +     * recover the struct page_info * uniformly at teardown, which is
>> +     * needed to support multi-page ioreq mappings (see nr_ioreq_pages()).
>> +     */
> 
> "is needed" is too strong, I think - surely there would be a way to handle
> that without vmap_to_page(), by tracking all struct page_info * separately.
> 
>> @@ -309,15 +310,16 @@ static int ioreq_server_alloc_mfn(struct ioreq_server 
>> *s, bool buf)
>>   static void ioreq_server_free_mfn(struct ioreq_server *s, bool buf)
>>   {
>>       struct ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
>> -    struct page_info *page = iorp->page;
>> +    struct page_info *page;
>> +    void *va;
>>   
>> -    if ( !page )
>> +    if ( !iorp->va )
>>           return;
>>   
>> -    iorp->page = NULL;
>> -
>> -    unmap_domain_page_global(iorp->va);
>> +    va = iorp->va;
> 
> Please can this be the initializer of the variable, for the if() above to
> then use that local var?
> 
>> @@ -333,7 +335,8 @@ bool is_ioreq_server_page(struct domain *d, const struct 
>> page_info *page)
>>   
>>       FOR_EACH_IOREQ_SERVER(d, id, s)
>>       {
>> -        if ( (s->ioreq.page == page) || (s->bufioreq.page == page) )
>> +        if ( (s->ioreq.va && vmap_to_page(s->ioreq.va) == page) ||
>> +             (s->bufioreq.va && vmap_to_page(s->bufioreq.va) == page) )
>>           {
>>               found = true;
>>               break;
> 
> You mention in the description that some extra overhead is introduced. The
> (generally) two page walks done here are particularly concerning. Since we
> have a valid struct page_info * available here, I wonder if we shouldn't
> aid this lookup by recording the VA in one of struct page_info's fields.
> Afaics vmap() doesn't use any of the fields, so it should be relatively
> easy to determine a field to use for this purpose. The more involved part
> would then be to make sure the field (in other struct page_info instances)
> is also properly different from any VA vmap() may return.

Hello Jan,

Thank you again for your feedback! I will wait then for Anthony's 
decision regarding whether the multi-page ioreq support and the ioreq_t 
growth should be combined into a single effort, before I proceed further 
with a v7.

I just wanted to clarify one thing regarding the overhead I mentioned in 
the first patch's commit message ("this change has a small overhead in 
the common case"). Here, I was referring to vmap()/vunmap() replacing 
map_domain_page_global(). Where map_domain_page_global() has a directmap 
fast path. I didn't mean the overhead of the added vmap_to_page(). I 
should maybe clarify this better in my next iteration's commit message.

On your suggestion to cache the VA in struct page_info to speed up the 
vmap_to_page() lookups in is_ioreq_server_page(): I looked through the 
tree, and that function currently has only one caller 
sh_remove_all_mappings() (in xen/arch/x86/mm/shadow/common.c) and is 
only reached in a failure case. Given that, and given how widely shared 
and size-critical struct page_info is, I'm wondering whether it's really 
worth touching it for the gain of not having to do the 2 lookups. What 
do you think?

Thanks,
Julian

>
> Jan



--
 | Vates

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.