|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH for-4.12 v3 3/5] xen/arm: p2m: Add support for preemption in p2m_cache_flush_range
On Fri, 14 Dec 2018, Julien Grall wrote:
> p2m_cache_flush_range does not yet support preemption, this may be an
> issue as cleaning the cache can take a long time. While the current
> caller (XEN_DOMCTL_cacheflush) does not stricly require preemption, this
> will be necessary for new caller in a follow-up patch.
>
> The preemption implemented is quite simple, a counter is incremented by:
> - 1 on region skipped
> - 10 for each page requiring a flush
>
> When the counter reach 512 or above, we will check if preemption is
> needed. If not, the counter will be reset to 0. If yes, the function
> will stop, update start (to allow resuming later on) and return
> -ERESTART. This allows the caller to decide how the preemption will be
> done.
>
> For now, XEN_DOMCTL_cacheflush will continue to ignore the preemption.
>
> Signed-off-by: Julien Grall <julien.grall@xxxxxxx>
>
> ---
> Changes in v2:
> - Patch added
> ---
> xen/arch/arm/domctl.c | 8 +++++++-
> xen/arch/arm/p2m.c | 35 ++++++++++++++++++++++++++++++++---
> xen/include/asm-arm/p2m.h | 4 +++-
> 3 files changed, 42 insertions(+), 5 deletions(-)
>
> diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
> index 20691528a6..9da88b8c64 100644
> --- a/xen/arch/arm/domctl.c
> +++ b/xen/arch/arm/domctl.c
> @@ -54,6 +54,7 @@ long arch_do_domctl(struct xen_domctl *domctl, struct
> domain *d,
> {
> gfn_t s = _gfn(domctl->u.cacheflush.start_pfn);
> gfn_t e = gfn_add(s, domctl->u.cacheflush.nr_pfns);
> + int rc;
>
> if ( domctl->u.cacheflush.nr_pfns > (1U<<MAX_ORDER) )
> return -EINVAL;
> @@ -61,7 +62,12 @@ long arch_do_domctl(struct xen_domctl *domctl, struct
> domain *d,
> if ( gfn_x(e) < gfn_x(s) )
> return -EINVAL;
>
> - return p2m_cache_flush_range(d, s, e);
> + /* XXX: Handle preemption */
> + do
> + rc = p2m_cache_flush_range(d, &s, e);
> + while ( rc == -ERESTART );
> +
> + return rc;
> }
> case XEN_DOMCTL_bind_pt_irq:
> {
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 17e2523fc1..5639e4b64c 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -1524,13 +1524,17 @@ int relinquish_p2m_mapping(struct domain *d)
> return rc;
> }
>
> -int p2m_cache_flush_range(struct domain *d, gfn_t start, gfn_t end)
> +int p2m_cache_flush_range(struct domain *d, gfn_t *pstart, gfn_t end)
> {
> struct p2m_domain *p2m = p2m_get_hostp2m(d);
> gfn_t next_block_gfn;
> + gfn_t start = *pstart;
> mfn_t mfn = INVALID_MFN;
> p2m_type_t t;
> unsigned int order;
> + int rc = 0;
> + /* Counter for preemption */
> + unsigned long count = 0;
No need for unsigned long, count could be unsigned int or even unsigned
short.
With this change:
Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx>
> /*
> * The operation cache flush will invalidate the RAM assigned to the
> @@ -1547,6 +1551,25 @@ int p2m_cache_flush_range(struct domain *d, gfn_t
> start, gfn_t end)
>
> while ( gfn_x(start) < gfn_x(end) )
> {
> + /*
> + * Cleaning the cache for the P2M may take a long time. So we
> + * need to be able to preempt. We will arbitrarily preempt every
> + * time count reach 512 or above.
> + *
> + * The count will be incremented by:
> + * - 1 on region skipped
> + * - 10 for each page requiring a flush
> + */
> + if ( count >= 512 )
> + {
> + if ( softirq_pending(smp_processor_id()) )
> + {
> + rc = -ERESTART;
> + break;
> + }
> + count = 0;
> + }
> +
> /*
> * We want to flush page by page as:
> * - it may not be possible to map the full block (can be up to 1GB)
> @@ -1568,22 +1591,28 @@ int p2m_cache_flush_range(struct domain *d, gfn_t
> start, gfn_t end)
>
> if ( mfn_eq(mfn, INVALID_MFN) || !p2m_is_any_ram(t) )
> {
> + count++;
> start = next_block_gfn;
> continue;
> }
> }
>
> + count += 10;
> +
> flush_page_to_ram(mfn_x(mfn), false);
>
> start = gfn_add(start, 1);
> mfn = mfn_add(mfn, 1);
> }
>
> - invalidate_icache();
> + if ( rc != -ERESTART )
> + invalidate_icache();
>
> p2m_read_unlock(p2m);
>
> - return 0;
> + *pstart = start;
> +
> + return rc;
> }
>
> mfn_t gfn_to_mfn(struct domain *d, gfn_t gfn)
> diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
> index 7c1d930b1d..a633e27cc9 100644
> --- a/xen/include/asm-arm/p2m.h
> +++ b/xen/include/asm-arm/p2m.h
> @@ -232,8 +232,10 @@ bool p2m_resolve_translation_fault(struct domain *d,
> gfn_t gfn);
> /*
> * Clean & invalidate caches corresponding to a region [start,end) of guest
> * address space.
> + *
> + * start will get updated if the function is preempted.
> */
> -int p2m_cache_flush_range(struct domain *d, gfn_t start, gfn_t end);
> +int p2m_cache_flush_range(struct domain *d, gfn_t *pstart, gfn_t end);
>
> /*
> * Map a region in the guest p2m with a specific p2m type.
> --
> 2.11.0
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |