|
[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 07.02.22 19:15, Julien Grall wrote:
> Hi Oleksandr,
Hi Julien
>
>
> 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".
ok, will do
>
> [...]
>
>> 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?
>
>
>> })
>> #define gnttab_get_frame_gfn(gt, st, idx)
>> ({ \
>> @@ -88,11 +54,21 @@ int replace_grant_host_mapping(unsigned long
>> gpaddr, mfn_t mfn,
>> : gnttab_shared_gfn(NULL, gt,
>> idx); \
>> })
>> -#define gnttab_shared_gfn(d, t,
>> i) \
>> - (((i) >= nr_grant_frames(t)) ? INVALID_GFN :
>> (t)->arch.shared_gfn[i])
>> +#define gnttab_shared_page(t, i)
>> ({ \
>> + virt_to_page((t)->shared_raw[i]); \
>> +})
>
> This can be simplified to:
>
> #define gnttab_shared_page(t, i) virt_to_page((t)->shared_raw[i])
agree, will do
>
>> +
>> +#define gnttab_status_page(t, i)
>> ({ \
>> + virt_to_page((t)->status[i]); \
>> +})
>
> Same here.
ok
>
>> -#define gnttab_status_gfn(d, t,
>> i) \
>> - (((i) >= nr_status_frames(t)) ? INVALID_GFN :
>> (t)->arch.status_gfn[i])
>> +#define gnttab_shared_gfn(d, t, i)
>> ({ \
>> + page_get_xenheap_gfn(gnttab_shared_page(t,
>> i)); \
>> +})
>
> Same here
ok
>
>> +
>> +#define gnttab_status_gfn(d, t, i)
>> ({ \
>> + page_get_xenheap_gfn(gnttab_status_page(t,
>> i)); \
>> +})
>
> Same here.
ok
>
>> #define gnttab_need_iommu_mapping(d) \
>> (is_domain_direct_mapped(d) && is_iommu_enabled(d))
>> diff --git a/xen/arch/arm/include/asm/mm.h
>> b/xen/arch/arm/include/asm/mm.h
>> index 424aaf2..b99044c 100644
>> --- a/xen/arch/arm/include/asm/mm.h
>> +++ b/xen/arch/arm/include/asm/mm.h
>> @@ -98,9 +98,22 @@ struct page_info
>> #define PGT_writable_page PG_mask(1, 1) /* has writable
>> mappings? */
>> #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)
>> + /* 2-bit count of uses of this frame as its current type. */
>> +#define PGT_count_mask PG_mask(3, 3)
>> +
>> +/*
>> + * Stored in bits [28:0] or [60:0] GFN if page is xenheap page.
>
> This comment would be easier to understand if you add resp. (arm32)
> and (arm64) after each range.
agree, will do
>
>
>> + */
>> +#define PGT_gfn_width PG_shift(3)
>> +#define PGT_gfn_mask ((1UL<<PGT_gfn_width)-1)
>> +
>> +#define PGT_INVALID_XENHEAP_GFN _gfn(PGT_gfn_mask)
>> +
>> +/*
>> + * An arch-specific initialization pattern is needed for the
>> type_info field
>> + * as it's GFN portion can contain the valid GFN if page is xenheap
>> page.
>> + */
>> +#define PGT_TYPE_INFO_INIT_PATTERN gfn_x(PGT_INVALID_XENHEAP_GFN)
>> /* Cleared when the owning guest 'frees' this page. */
>> #define _PGC_allocated PG_shift(1)
>> @@ -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.
>
>
> I will do another review of the patch once I know what we locking
> should protect the accesses.
>
> Cheers,
>
--
Regards,
Oleksandr Tyshchenko
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |