|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH V5] xen/gnttab: Store frame GFN in struct page_info on Arm
On 08.02.22 14:47, Jan Beulich wrote:
Hi Julien, Jan
> On 08.02.2022 12:58, Julien Grall wrote:
>> On 07/02/2022 19:56, Oleksandr Tyshchenko wrote:
>>> On 07.02.22 19:15, Julien Grall wrote:
>>>> Hi Oleksandr,
>>>> On 05/01/2022 23:11, Oleksandr Tyshchenko wrote:
>>>>> From: Oleksandr Tyshchenko <oleksandr_tyshchenko@xxxxxxxx>
>>>>>
>>>>> Rework Arm implementation to store grant table frame GFN
>>>>> in struct page_info directly instead of keeping it in
>>>>> standalone status/shared arrays. This patch is based on
>>>>> the assumption that grant table page is the xenheap page.
>>>> I would write "grant table pages are xenheap pages" or "a grant table
>>>> page is a xenheap page".
>>>>
>>>> [...]
>>>>
>>>>> diff --git a/xen/arch/arm/include/asm/grant_table.h
>>>>> b/xen/arch/arm/include/asm/grant_table.h
>>>>> index d31a4d6..d6fda31 100644
>>>>> --- a/xen/arch/arm/include/asm/grant_table.h
>>>>> +++ b/xen/arch/arm/include/asm/grant_table.h
>>>>> @@ -11,11 +11,6 @@
>>>>> #define INITIAL_NR_GRANT_FRAMES 1U
>>>>> #define GNTTAB_MAX_VERSION 1
>>>>> -struct grant_table_arch {
>>>>> - gfn_t *shared_gfn;
>>>>> - gfn_t *status_gfn;
>>>>> -};
>>>>> -
>>>>> static inline void gnttab_clear_flags(struct domain *d,
>>>>> unsigned int mask, uint16_t
>>>>> *addr)
>>>>> {
>>>>> @@ -46,41 +41,12 @@ int replace_grant_host_mapping(unsigned long
>>>>> gpaddr, mfn_t mfn,
>>>>> #define gnttab_dom0_frames() \
>>>>> min_t(unsigned int, opt_max_grant_frames, PFN_DOWN(_etext -
>>>>> _stext))
>>>>> -#define gnttab_init_arch(gt) \
>>>>> -({ \
>>>>> - unsigned int ngf_ =
>>>>> (gt)->max_grant_frames; \
>>>>> - unsigned int nsf_ =
>>>>> grant_to_status_frames(ngf_); \
>>>>> - \
>>>>> - (gt)->arch.shared_gfn = xmalloc_array(gfn_t,
>>>>> ngf_); \
>>>>> - (gt)->arch.status_gfn = xmalloc_array(gfn_t,
>>>>> nsf_); \
>>>>> - if ( (gt)->arch.shared_gfn && (gt)->arch.status_gfn
>>>>> ) \
>>>>> - { \
>>>>> - while ( ngf_--
>>>>> ) \
>>>>> - (gt)->arch.shared_gfn[ngf_] =
>>>>> INVALID_GFN; \
>>>>> - while ( nsf_--
>>>>> ) \
>>>>> - (gt)->arch.status_gfn[nsf_] =
>>>>> INVALID_GFN; \
>>>>> - } \
>>>>> - else \
>>>>> - gnttab_destroy_arch(gt); \
>>>>> - (gt)->arch.shared_gfn ? 0 :
>>>>> -ENOMEM; \
>>>>> -})
>>>>> -
>>>>> -#define gnttab_destroy_arch(gt) \
>>>>> - do { \
>>>>> - XFREE((gt)->arch.shared_gfn); \
>>>>> - XFREE((gt)->arch.status_gfn); \
>>>>> - } while ( 0 )
>>>>> -
>>>>> #define gnttab_set_frame_gfn(gt, st, idx, gfn,
>>>>> mfn) \
>>>>> ({ \
>>>>> - int rc_ =
>>>>> 0; \
>>>>> gfn_t ogfn = gnttab_get_frame_gfn(gt, st,
>>>>> idx); \
>>>>> - if ( gfn_eq(ogfn, INVALID_GFN) || gfn_eq(ogfn, gfn)
>>>>> || \
>>>>> - (rc_ = guest_physmap_remove_page((gt)->domain, ogfn,
>>>>> mfn, \
>>>>> - 0)) == 0
>>>>> ) \
>>>>> - ((st) ?
>>>>> (gt)->arch.status_gfn \
>>>>> - : (gt)->arch.shared_gfn)[idx] =
>>>>> (gfn); \
>>>>> - rc_; \
>>>>> + (!gfn_eq(ogfn, INVALID_GFN) && !gfn_eq(ogfn,
>>>>> gfn)) \
>>>>> + ? guest_physmap_remove_page((gt)->domain, ogfn, mfn,
>>>>> 0) \
>>>>> + :
>>>>> 0; \
>>>> Given that we are implementing something similar to an M2P, I was
>>>> expecting the implementation to be pretty much the same as the x86
>>>> helper.
>>>>
>>>> Would you be able to outline why it is different?
>>> Being honest, I didn't think about it so far. But, I agree with the
>>> question.
>>>
>>> It feels to me that Arm variant can now behave as x86 one (as
>>> xenmem_add_to_physmap_one() now checks for the prior mapping), I mean to
>>> use INVALID_GFN as an indication to remove a page.
>>>
>>> What do you think?
>> I will defer that to Jan.
>>
>> Jan, IIRC you were the one introducing the call to
>> guest_physmap_remove_page(). Do you remember why the difference between
>> x86 and Arm were necessary?
> The code was different before, and Arm's behavior was also different.
> Hence the two functions couldn't be quite similar. If Arm behavior is
> now converging with x86'es, the functions becoming more similar is
> not entirely unexpected.
If Arm's gnttab_set_frame_gfn appears to be the similar to x86's one,
what would be the next step?
I thought of the following options:
1. Leave per-arch helpers as they are
2. Move helper to the common grant_table.h
3. Remove the helpers, call guest_physmap_remove_page() directly from
the common grant_table.c
>
>>>>> @@ -358,6 +371,25 @@ void clear_and_clean_page(struct page_info *page);
>>>>> unsigned int arch_get_dma_bitsize(void);
>>>>> +static inline gfn_t page_get_xenheap_gfn(const struct page_info *p)
>>>>> +{
>>>>> + gfn_t gfn_ = _gfn(p->u.inuse.type_info & PGT_gfn_mask);
>>>>> +
>>>>> + ASSERT(is_xen_heap_page(p));
>>>>> +
>>>>> + return gfn_eq(gfn_, PGT_INVALID_XENHEAP_GFN) ? INVALID_GFN : gfn_;
>>>>> +}
>>>>> +
>>>>> +static inline void page_set_xenheap_gfn(struct page_info *p, gfn_t gfn)
>>>>> +{
>>>>> + gfn_t gfn_ = gfn_eq(gfn, INVALID_GFN) ? PGT_INVALID_XENHEAP_GFN
>>>>> : gfn;
>>>>> +
>>>>> + ASSERT(is_xen_heap_page(p));
>>>>> +
>>>>> + p->u.inuse.type_info &= ~PGT_gfn_mask;
>>>>> + p->u.inuse.type_info |= gfn_x(gfn_);
>>>>> +}
>>>> This is not going to be atomic. So can you outline which locking
>>>> mechanism should be used to protect access (set/get) to the GFN?
>>>
>>> I think, the P2M lock.
>> Ok. So, looking at the code, most of calls to page_get_xenheap_gfn() are
>> not protected with the p2m_lock().
>>
>> (Jan please confirm) If I am not mistaken, on x86, a read to the M2P is
>> not always protected. But they have code within the P2M lock to check
>> any difference (see p2m_remove_page()). I think we would need the same,
>> so we don't end up to introduce a behavior similar to what XSA-387 has
>> fixed on x86.
> Yes, this matches my understanding.
>
> Jan
>
--
Regards,
Oleksandr Tyshchenko
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |