|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [RFC PATCH] xen/gnttab: Store frame GFN in struct page_info on Arm
On 13.09.2021 19:09, Oleksandr wrote:
> On 10.09.21 10:52, Jan Beulich wrote:
>> On 10.09.2021 01:04, Oleksandr Tyshchenko wrote:
>>> @@ -731,11 +733,19 @@ static void p2m_put_l3_page(const lpae_t pte)
>>> */
>>> if ( p2m_is_foreign(pte.p2m.type) )
>>> {
>>> - mfn_t mfn = lpae_get_mfn(pte);
>>> -
>>> ASSERT(mfn_valid(mfn));
>>> put_page(mfn_to_page(mfn));
>>> }
>>> +
>>> +#ifdef CONFIG_GRANT_TABLE
>>> + /*
>>> + * Check whether we deal with grant table page. As the grant table page
>>> + * is xen_heap page and its entry has known p2m type, detect it and
>>> mark
>>> + * the stored GFN as invalid.
>>> + */
>>> + if ( p2m_is_ram(pte.p2m.type) && is_xen_heap_mfn(mfn) )
>>> + page_set_frame_gfn(mfn_to_page(mfn), INVALID_GFN);
>>> +#endif
>> I take it the write done is benign for other Xen heap pages? I suppose
>> this would want making very explicit, as such an assumption is easy to
>> go stale by entirely unrelated changes.
>
> Yes, I don't see what bad could happen if we would clear this field for
> non grant table pages. Except grant table pages I could detect only one
> page passed this check here which is, I assume, shared_info page. All
> pages have this field initialized with INVALID_GFN. But *only* grant
> table pages have this field in use. So, I think, no one will suffer. I
> will add a comment. Or you meant something more than just a comment?
The answer here goes hand in hand with the pending question of whether
you wouldn't better generally introduce recording of the GFN (and hence
effectively an M2P): The less special casing here, the better imo. The
more special casing here, the more justification / explanation is imo
needed in the comment.
>>> --- a/xen/include/asm-arm/mm.h
>>> +++ b/xen/include/asm-arm/mm.h
>>> @@ -39,7 +39,15 @@ struct page_info
>>> /* Page is in use: ((count_info & PGC_count_mask) != 0). */
>>> struct {
>>> /* Type reference count and various PGT_xxx flags and fields.
>>> */
>>> - unsigned long type_info;
>>> + unsigned long type_info:4;
>>> +
>>> + /*
>>> + * Stored GFN if page is used for grant table frame
>>> + * (bits 59(27)-0).
>> Are these bit numbers correct? I thought Arm, like x86, counted bits
>> from low to high (unlike PPC, for example)?
>
> I think, these are correct. Yes, Little Endian is used.
Well, the low 4 bits are used by type_info here. Therefore I'm having
trouble seeing what the 0 refers to.
>>> @@ -94,12 +102,12 @@ struct page_info
>>> #define PG_shift(idx) (BITS_PER_LONG - (idx))
>>> #define PG_mask(x, idx) (x ## UL << PG_shift(idx))
>>>
>>> -#define PGT_none PG_mask(0, 1) /* no special uses of this page
>>> */
>>> -#define PGT_writable_page PG_mask(1, 1) /* has writable mappings?
>>> */
>>> -#define PGT_type_mask PG_mask(1, 1) /* Bits 31 or 63.
>>> */
>>> +#define PGT_none (0UL << 3) /* no special uses of this page */
>>> +#define PGT_writable_page (1UL << 3) /* has writable mappings? */
>>> +#define PGT_type_mask (1UL << 3)
>>>
>>> /* Count of uses of this frame as its current type. */
>>> -#define PGT_count_width PG_shift(2)
>>> +#define PGT_count_width 1
>>> #define PGT_count_mask ((1UL<<PGT_count_width)-1)
>> Leaving just a single bit seems pretty risky to me, and I can't see
>> why you do so. You need 52 bits on Arm64. Which means you have 12
>> bits left. Why not use them in full? Even on Arm32 you have 3 bits
>> available for the count afaict.
>
> Only 1 bit in the type_info field is really used on Arm, but anyway ...
>
>
>>
>> Also there's a disconnect here: If anyone wanted to change the number
>> of bits used for the various fields, each such change should require
>> an adjustment in as few independent places as possible. That is, there
>> shouldn't be multiple uses of literal 4 further up, and there also
>> shouldn't be a hidden connection between that 4 and the PGT_* values
>> here. I think you'd better express the GFN as such a PGT_* construct
>> as well. And you better would keep using PG_mask() and PG_shift().
>
> ... I think, this indeed makes sense. If got your request correctly, we
> can avoid disconnect here
> and reserve 3-bit field for count for both Arm32 and Arm64. The struct
> page_info's type_info field remains untouched.
>
>
> diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
> index ded74d2..8b73e1c 100644
> --- a/xen/include/asm-arm/mm.h
> +++ b/xen/include/asm-arm/mm.h
> @@ -99,8 +99,14 @@ struct page_info
> #define PGT_type_mask PG_mask(1, 1) /* Bits 31 or
> 63. */
>
> /* Count of uses of this frame as its current type. */
> -#define PGT_count_width PG_shift(2)
> -#define PGT_count_mask ((1UL<<PGT_count_width)-1)
> +#define PGT_count_base PG_shift(4)
> +#define PGT_count_mask PG_mask(7, 4)
> +
> +/* Stored in bits [27:0] or [59:0] GFN if page is used for grant table
> frame */
> +#define PGT_gfn_width PG_shift(4)
> +#define PGT_gfn_mask ((1UL<<PGT_gfn_width)-1)
> +
> +#define PGT_INVALID_FRAME_GFN _gfn(PGT_gfn_mask)
>
> /* Cleared when the owning guest 'frees' this page. */
> #define _PGC_allocated PG_shift(1)
> @@ -163,6 +169,22 @@ extern unsigned long xenheap_base_pdx;
>
> #define maddr_get_owner(ma) (page_get_owner(maddr_to_page((ma))))
>
> +#define page_get_frame_gfn(_p) ({ \
> + gfn_t gfn_ = _gfn((_p)->u.inuse.type_info & PGT_gfn_mask); \
> + gfn_eq(gfn_, PGT_INVALID_FRAME_GFN) ? INVALID_GFN : gfn_; \
> +})
> +
> +#define page_set_frame_gfn(_p, _gfn) ({ \
> + gfn_t gfn_ = gfn_eq(_gfn, INVALID_GFN) ? \
> + PGT_INVALID_FRAME_GFN : _gfn; \
> + (_p)->u.inuse.type_info &= ~PGT_gfn_mask; \
> + (_p)->u.inuse.type_info |= gfn_x(gfn_); \
> +})
>
> [snip]
>
> Is it close to what you keep in mind?
Yes. Just to be sure - did you check that moving the count up
from starting at bit 0 is compatible with all present uses? At
least on x86 I think we have uses where it is assumed to occupy
the bottom so many bits (and the same also for PGC_count_mask).
Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |